using System.Text.Json; using System.Text.Json.Serialization; namespace Uwaa.HTTP; //TODO: Add support for parameters /// /// Represents a Multipurpose Internet Mail Extensions type, which indicates the nature and format of a document/file/chunk of data. /// [JsonConverter(typeof(MIMETypeConverter))] public readonly record struct MIMEType { public static explicit operator string(MIMEType type) => type.ToString(); public static implicit operator MIMEType(string type) => new MIMEType(type); /// /// The first part of the MIME type, representing the general category into which the data type falls. /// public readonly string? Type { get; init; } /// /// The second part of the MIME type, identifying the exact kind of data the MIME type represents. /// public readonly string? Subtype { get; init; } /// /// Parses a MIME type string. /// /// The string to parse. /// Thrown if MIME type is missing a subtype. public MIMEType(ReadOnlySpan text) { if (text == "*/*") { Type = null; Subtype = null; return; } int spl = text.IndexOf('/'); if (spl == -1) { //MIME types need a subtype to be valid. throw new FormatException("The provided MIME type is missing a subtype."); } int end = text.IndexOf(';'); if (end == -1) end = text.Length; if (spl == 1 && text[0] == '*') Type = null; else Type = new string(text[..spl]); if (spl == text.Length - 2 && text[^1] == '*') Subtype = null; else Subtype = new string(text[(spl + 1)..end]); } /// /// Constructs a MIME type from its two components. /// public MIMEType(string? type, string? subType) { Type = type; Subtype = subType; } /// /// Determines if the given MIME type matches the pattern specified by this MIME type. /// public readonly bool Match(MIMEType type) { return (Type == null || Type.Equals(type.Type, StringComparison.OrdinalIgnoreCase)) && (Subtype == null || Subtype.Equals(type.Subtype, StringComparison.OrdinalIgnoreCase)); } /// /// Generates a string for the MIME type. /// public override readonly string ToString() => $"{Type ?? "*"}/{Subtype ?? "*"}"; } class MIMETypeConverter : JsonConverter { public sealed override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(MIMEType); public override MIMEType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { string? str = reader.GetString() ?? throw new JsonException("Cannot read MIME type"); return new MIMEType(str); } public override void Write(Utf8JsonWriter writer, MIMEType status, JsonSerializerOptions options) { writer.WriteStringValue(status.ToString()); } }