LCOV - code coverage report
Current view: top level - http_parser-4.0.0/lib/src - media_type.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 41 55 74.5 %
Date: 2021-11-28 14:37:50 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
       2             : // for details. All rights reserved. Use of this source code is governed by a
       3             : // BSD-style license that can be found in the LICENSE file.
       4             : 
       5             : import 'package:collection/collection.dart';
       6             : import 'package:string_scanner/string_scanner.dart';
       7             : 
       8             : import 'case_insensitive_map.dart';
       9             : import 'scan.dart';
      10             : import 'utils.dart';
      11             : 
      12             : /// A regular expression matching a character that needs to be backslash-escaped
      13             : /// in a quoted string.
      14           0 : final _escapedChar = RegExp(r'["\x00-\x1F\x7F]');
      15             : 
      16             : /// A class representing an HTTP media type, as used in Accept and Content-Type
      17             : /// headers.
      18             : ///
      19             : /// This is immutable; new instances can be created based on an old instance by
      20             : /// calling [change].
      21             : class MediaType {
      22             :   /// The primary identifier of the MIME type.
      23             :   ///
      24             :   /// This is always lowercase.
      25             :   final String type;
      26             : 
      27             :   /// The secondary identifier of the MIME type.
      28             :   ///
      29             :   /// This is always lowercase.
      30             :   final String subtype;
      31             : 
      32             :   /// The parameters to the media type.
      33             :   ///
      34             :   /// This map is immutable and the keys are case-insensitive.
      35             :   final Map<String, String> parameters;
      36             : 
      37             :   /// The media type's MIME type.
      38          20 :   String get mimeType => '$type/$subtype';
      39             : 
      40             :   /// Parses a media type.
      41             :   ///
      42             :   /// This will throw a FormatError if the media type is invalid.
      43           5 :   factory MediaType.parse(String mediaType) =>
      44             :       // This parsing is based on sections 3.6 and 3.7 of the HTTP spec:
      45             :       // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html.
      46          10 :       wrapFormatException('media type', mediaType, () {
      47           5 :         final scanner = StringScanner(mediaType);
      48          10 :         scanner.scan(whitespace);
      49          10 :         scanner.expect(token);
      50          10 :         final type = scanner.lastMatch![0]!;
      51           5 :         scanner.expect('/');
      52          10 :         scanner.expect(token);
      53          10 :         final subtype = scanner.lastMatch![0]!;
      54          10 :         scanner.scan(whitespace);
      55             : 
      56           5 :         final parameters = <String, String>{};
      57           5 :         while (scanner.scan(';')) {
      58          10 :           scanner.scan(whitespace);
      59          10 :           scanner.expect(token);
      60          10 :           final attribute = scanner.lastMatch![0]!;
      61           5 :           scanner.expect('=');
      62             : 
      63             :           String value;
      64          10 :           if (scanner.scan(token)) {
      65          10 :             value = scanner.lastMatch![0]!;
      66             :           } else {
      67           0 :             value = expectQuotedString(scanner);
      68             :           }
      69             : 
      70          10 :           scanner.scan(whitespace);
      71           5 :           parameters[attribute] = value;
      72             :         }
      73             : 
      74           5 :         scanner.expectDone();
      75           5 :         return MediaType(type, subtype, parameters);
      76             :       });
      77             : 
      78           6 :   MediaType(String type, String subtype, [Map<String, String>? parameters])
      79           6 :       : type = type.toLowerCase(),
      80           6 :         subtype = subtype.toLowerCase(),
      81           6 :         parameters = UnmodifiableMapView(
      82           7 :             parameters == null ? {} : CaseInsensitiveMap.from(parameters));
      83             : 
      84             :   /// Returns a copy of this [MediaType] with some fields altered.
      85             :   ///
      86             :   /// [type] and [subtype] alter the corresponding fields. [mimeType] is parsed
      87             :   /// and alters both the [type] and [subtype] fields; it cannot be passed along
      88             :   /// with [type] or [subtype].
      89             :   ///
      90             :   /// [parameters] overwrites and adds to the corresponding field. If
      91             :   /// [clearParameters] is passed, it replaces the corresponding field entirely
      92             :   /// instead.
      93           1 :   MediaType change(
      94             :       {String? type,
      95             :       String? subtype,
      96             :       String? mimeType,
      97             :       Map<String, String>? parameters,
      98             :       bool clearParameters = false}) {
      99             :     if (mimeType != null) {
     100             :       if (type != null) {
     101           0 :         throw ArgumentError('You may not pass both [type] and [mimeType].');
     102             :       } else if (subtype != null) {
     103           0 :         throw ArgumentError('You may not pass both [subtype] and '
     104             :             '[mimeType].');
     105             :       }
     106             : 
     107           0 :       final segments = mimeType.split('/');
     108           0 :       if (segments.length != 2) {
     109           0 :         throw FormatException('Invalid mime type "$mimeType".');
     110             :       }
     111             : 
     112           0 :       type = segments[0];
     113           0 :       subtype = segments[1];
     114             :     }
     115             : 
     116           1 :     type ??= this.type;
     117           1 :     subtype ??= this.subtype;
     118           0 :     parameters ??= {};
     119             : 
     120             :     if (!clearParameters) {
     121             :       final newParameters = parameters;
     122           2 :       parameters = Map.from(this.parameters);
     123           1 :       parameters.addAll(newParameters);
     124             :     }
     125             : 
     126           1 :     return MediaType(type, subtype, parameters);
     127             :   }
     128             : 
     129             :   /// Converts the media type to a string.
     130             :   ///
     131             :   /// This will produce a valid HTTP media type.
     132           1 :   @override
     133             :   String toString() {
     134           6 :     final buffer = StringBuffer()..write(type)..write('/')..write(subtype);
     135             : 
     136           3 :     parameters.forEach((attribute, value) {
     137           2 :       buffer.write('; $attribute=');
     138           2 :       if (nonToken.hasMatch(value)) {
     139             :         buffer
     140           0 :           ..write('"')
     141           0 :           ..write(
     142           0 :               value.replaceAllMapped(_escapedChar, (match) => '\\${match[0]}'))
     143           0 :           ..write('"');
     144             :       } else {
     145           1 :         buffer.write(value);
     146             :       }
     147             :     });
     148             : 
     149           1 :     return buffer.toString();
     150             :   }
     151             : }

Generated by: LCOV version 1.14