Add RIFF container support.
This commit is contained in:
parent
ccf46a765c
commit
f9792e2bcf
105
ReMime/ContentResolvers/RiffResolver.cs
Normal file
105
ReMime/ContentResolvers/RiffResolver.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace ReMime.ContentResolvers
|
||||||
|
{
|
||||||
|
public class RiffResolver : IMediaTypeResolver, IMediaContentResolver
|
||||||
|
{
|
||||||
|
public readonly List<MediaType> _mediaTypes = new List<MediaType>();
|
||||||
|
public readonly Dictionary<string, MediaType> _extensions = new Dictionary<string, MediaType>();
|
||||||
|
public readonly Dictionary<int, MediaType> _magicValues = new Dictionary<int, MediaType>();
|
||||||
|
|
||||||
|
public IReadOnlyCollection<MediaType> MediaTypes { get; }
|
||||||
|
|
||||||
|
public RiffResolver()
|
||||||
|
{
|
||||||
|
MediaTypes = _mediaTypes.AsReadOnly();
|
||||||
|
|
||||||
|
List<MagicValueDatabaseEntry> entries;
|
||||||
|
|
||||||
|
using (Stream str = typeof(MagicContentResolver).Assembly.GetManifestResourceStream("ReMime.ContentResolvers.riff.jsonc")!)
|
||||||
|
{
|
||||||
|
entries = MagicValueDatabaseEntry.GetEntries(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var entry in entries)
|
||||||
|
{
|
||||||
|
AddRiffType((MagicValueMediaType)entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RiffResolver(IEnumerable<MagicValueMediaType> values) : this()
|
||||||
|
{
|
||||||
|
foreach (MagicValueMediaType value in values)
|
||||||
|
AddRiffType(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryResolve(Stream str, [NotNullWhen(true)] out MediaType? mediaType)
|
||||||
|
{
|
||||||
|
Span<byte> content = stackalloc byte[Unsafe.SizeOf<RiffChunk>()];
|
||||||
|
str.Read(content);
|
||||||
|
return TryResolve(content, out mediaType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryResolve(ReadOnlySpan<byte> content, [NotNullWhen(true)] out MediaType? mediaType)
|
||||||
|
{
|
||||||
|
mediaType = null;
|
||||||
|
|
||||||
|
if (content.Length < Unsafe.SizeOf<RiffChunk>())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ref readonly RiffChunk chunk = ref MemoryMarshal.Cast<byte, RiffChunk>(content)[0];
|
||||||
|
|
||||||
|
if (chunk.Riff != RiffChunk.RiffValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _magicValues.TryGetValue(chunk.FirstChunkType, out mediaType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryResolve(string extension, out MediaType? mediaType)
|
||||||
|
{
|
||||||
|
return _extensions.TryGetValue(extension, out mediaType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a RIFF sub-magic value to this resolver.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
public void AddRiffType(MagicValueMediaType type)
|
||||||
|
{
|
||||||
|
if (type.MagicValues.Length == 0)
|
||||||
|
throw new ArgumentException("Expected at least one media type.");
|
||||||
|
|
||||||
|
_mediaTypes.Add(type.MediaType);
|
||||||
|
|
||||||
|
foreach (string extension in type.Extensions)
|
||||||
|
{
|
||||||
|
_extensions.Add(extension, type.MediaType);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MagicValue magic in type.MagicValues)
|
||||||
|
{
|
||||||
|
if (magic.Value.Length != 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int i = MemoryMarshal.Cast<byte, int>(magic.Value)[0];
|
||||||
|
|
||||||
|
_magicValues.Add(i, type.MediaType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Auto, Size = 12)]
|
||||||
|
private struct RiffChunk
|
||||||
|
{
|
||||||
|
public int Riff;
|
||||||
|
public int Size;
|
||||||
|
public int FirstChunkType;
|
||||||
|
|
||||||
|
public const int RiffValue = 1179011410;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
ReMime/ContentResolvers/riff.jsonc
Normal file
21
ReMime/ContentResolvers/riff.jsonc
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* ReMime RIFF file types database.
|
||||||
|
* This is a self compiled list of magic values, file extensions and
|
||||||
|
* their media-types. Please contribute common file formats if you come
|
||||||
|
* across them.
|
||||||
|
*
|
||||||
|
* This file is only for RIFF based formats. Please do not add magic values
|
||||||
|
* for other file types here, as the magic values in this file are used
|
||||||
|
*/
|
||||||
|
[
|
||||||
|
{ "type": "video/avi", "magic": ["'AVI '"], "extensions": ["avi"]},
|
||||||
|
{ "type": "audio/wav", "magic": ["'WAVE'"], "extensions": ["wav"] },
|
||||||
|
{ "type": "image/vnd.microsoft.icon", "magic": ["'ACON'"], "extensions": ["ani"] },
|
||||||
|
|
||||||
|
// Whilst we speak about WEBP...
|
||||||
|
// My kindest f*ck you to Google for impeding standards like JPEG-XL
|
||||||
|
// for their own benefit. WEBP itself might be a fine file format
|
||||||
|
// but I do not support it if you maliciously stop implementing other
|
||||||
|
// file formats into your browsers and applications.
|
||||||
|
{ "type": "image/webp", "magic": ["'WEBP'"], "extensions": ["webp"] }
|
||||||
|
]
|
@ -50,6 +50,7 @@ namespace ReMime
|
|||||||
|
|
||||||
static MediaTypeResolver()
|
static MediaTypeResolver()
|
||||||
{
|
{
|
||||||
|
AddResolver(new RiffResolver(), 9997);
|
||||||
AddResolver(new MagicContentResolver(), 9998);
|
AddResolver(new MagicContentResolver(), 9998);
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="ContentResolvers/database.jsonc" />
|
<EmbeddedResource Include="ContentResolvers/database.jsonc" />
|
||||||
|
<EmbeddedResource Include="ContentResolvers/riff.jsonc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user