Uwaa/HTTP/MIMEType.cs

101 lines
3.2 KiB
C#
Raw Normal View History

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