diff --git a/ReMime.ReFile/Program.cs b/ReMime.ReFile/Program.cs
index 551caaf..4499e43 100644
--- a/ReMime.ReFile/Program.cs
+++ b/ReMime.ReFile/Program.cs
@@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using System.Linq;
+using Microsoft.VisualBasic;
namespace ReMime.Cli
{
@@ -47,7 +49,10 @@ namespace ReMime.Cli
[DoesNotReturn]
private static void ListTypes()
{
- foreach (MediaType type in MediaTypeResolver.KnownTypes)
+ var list = MediaTypeResolver.KnownTypes.ToList();
+ list.Sort();
+
+ foreach (MediaType type in list)
{
Console.WriteLine("{0}\t{1}", type.FullTypeNoParameters, string.Join(' ', type.Extensions));
}
diff --git a/ReMime.ReFile/ReMime.ReFile.csproj b/ReMime.ReFile/ReMime.ReFile.csproj
index 054f5c4..e80f971 100644
--- a/ReMime.ReFile/ReMime.ReFile.csproj
+++ b/ReMime.ReFile/ReMime.ReFile.csproj
@@ -9,7 +9,7 @@
True
ReFuel.ReMime.ReFile
- 0.1.0
+ 0.1.1
H. Utku Maden
ReFuel
README.md
@@ -34,7 +34,7 @@
-
+
diff --git a/ReMime.Tests/MediaTypesByExtension.cs b/ReMime.Tests/MediaTypesByExtension.cs
index d40e781..d1ded79 100644
--- a/ReMime.Tests/MediaTypesByExtension.cs
+++ b/ReMime.Tests/MediaTypesByExtension.cs
@@ -3,21 +3,9 @@ using ReMime.Platform;
namespace ReMime.Tests
{
- public abstract class MediaTypesByExtension where T : IMediaTypeResolver, new()
+ [TestClass]
+ public class MediaTypesByExtension
{
- private T CIT;
-
- protected MediaTypesByExtension()
- {
- Unsafe.SkipInit(out CIT);
- }
-
- [TestInitialize]
- public virtual void Initialize()
- {
- CIT = new T();
- }
-
readonly (string extension, string type)[] ExampleMimeTypes = new (string, string)[] {
("png", "image/png"),
("gif", "image/gif"),
@@ -34,44 +22,10 @@ namespace ReMime.Tests
{
foreach (var(ext, type) in ExampleMimeTypes)
{
- Assert.IsTrue(CIT.TryResolve(ext, out MediaType? result));
+ Assert.IsTrue(MediaTypeResolver.TryResolve(ext, out MediaType? result));
Assert.AreEqual(result!.FullType, type);
Assert.IsTrue(result.Extensions.Contains(ext));
}
}
}
-
- [TestClass]
- public class UnixMediaTypes : MediaTypesByExtension
- {
- [TestInitialize]
- public override void Initialize()
- {
- if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsFreeBSD())
- {
- base.Initialize();
- }
- else
- {
- Assert.Inconclusive("Cannot test this in this platform.");
- }
- }
- }
-
- [TestClass]
- public class Win32MediaTypes : MediaTypesByExtension
- {
- [TestInitialize]
- public override void Initialize()
- {
- if (OperatingSystem.IsWindows())
- {
- base.Initialize();
- }
- else
- {
- Assert.Inconclusive("Cannot test this in this platform.");
- }
- }
- }
}
diff --git a/ReMime/ContentResolvers/IMagicValueResolver.cs b/ReMime/ContentResolvers/IMagicValueResolver.cs
new file mode 100644
index 0000000..b8affb9
--- /dev/null
+++ b/ReMime/ContentResolvers/IMagicValueResolver.cs
@@ -0,0 +1,18 @@
+
+using System.Collections.Generic;
+
+namespace ReMime.ContentResolvers
+{
+ public interface IMagicValueResolver
+ {
+ void AddMagicValue(MagicValueMediaType value);
+
+ void AddMagicValues(IEnumerable values)
+ {
+ foreach (MagicValueMediaType value in values)
+ {
+ AddMagicValue(value);
+ }
+ }
+ }
+}
diff --git a/ReMime/ContentResolvers/MagEx.cs b/ReMime/ContentResolvers/MagEx.cs
new file mode 100644
index 0000000..59b84da
--- /dev/null
+++ b/ReMime/ContentResolvers/MagEx.cs
@@ -0,0 +1,86 @@
+
+using System;
+
+namespace ReMime.ContentResolvers
+{
+ /* You've heard of regular expressions, now prepare for magical expressions :sparkles:. */
+ ///
+ /// Bit pattern detecting state machine inspired by text regular expressions.
+ ///
+ public class MagEx
+ {
+ /**
+ * 0 1 2 3 4 5 6 7 8 9 a b c d e f 4-bit patterns to match.
+ * l h Single bit pattern.
+ * * Any bit pattern.
+ * ? Any 4-bit pattern.
+ * 'pattern' ASCII pattern with no terminator. Implies @.
+ * @ Align to 8-bits.
+ * % Align to 4-bits.
+ */
+
+ public string Pattern { get; }
+
+ public MagEx(string pattern)
+ {
+ Pattern = pattern;
+ }
+
+ public bool Match(ReadOnlySpan bytes)
+ {
+ byte current;
+ int needle;
+ int haystack;
+ int bits;
+ int pi = 0;
+ ReadOnlySpan ascii = ReadOnlySpan.Empty;
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ current = bytes[i];
+ bits = 8;
+
+ while (bits > 0)
+ {
+ char pat = Pattern[pi];
+ switch (pat)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9': case 'a': case 'A':
+ case 'b': case 'B': case 'c': case 'C':
+ case 'd': case 'D': case 'e': case 'E':
+ case 'f': case 'F':
+ haystack = current & 0xF;
+ current >>= 4;
+ bits -= 4;
+
+ if (pat >= '0' && pat <= '9')
+ {
+ needle = pat - '0';
+ }
+ else if (pat >= 'a' && pat <= 'f')
+ {
+ needle = pat - 'a';
+ }
+ else
+ {
+ needle = pat - 'A';
+ }
+
+ if (haystack == needle)
+ {
+ pi++;
+ }
+ else
+ {
+
+ }
+ break;
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ReMime/ContentResolvers/MagicResolver.cs b/ReMime/ContentResolvers/MagicContentResolver.cs
similarity index 90%
rename from ReMime/ContentResolvers/MagicResolver.cs
rename to ReMime/ContentResolvers/MagicContentResolver.cs
index 31330ce..774304e 100644
--- a/ReMime/ContentResolvers/MagicResolver.cs
+++ b/ReMime/ContentResolvers/MagicContentResolver.cs
@@ -6,30 +6,28 @@ using System.Linq;
namespace ReMime.ContentResolvers
{
- public record MagicValueMediaType(MediaType MediaType, MagicValue[] MagicValues, string[] Extensions);
+ public record MagicValueMediaType(MediaType MediaType, MagicValue[] MagicValues)
+ {
+ public IReadOnlyCollection Extensions { get; } = MediaType.Extensions;
+ }
- public class MagicContentResolver : IMediaContentResolver
+ public class MagicContentResolver : IMediaContentResolver, IMagicValueResolver
{
private readonly List _mediaTypes = new List();
private readonly Dictionary _extensions = new Dictionary();
private readonly Tree _tree = new Tree();
private int _maxBytes = 0;
- public MagicContentResolver(IEnumerable values) : this()
+ private MagicContentResolver()
{
- AddMagicValues(values);
- }
-
- public MagicContentResolver()
- {
- List entries;
+ IEnumerable entries;
using (Stream str = typeof(MagicContentResolver).Assembly.GetManifestResourceStream("ReMime.ContentResolvers.database.jsonc")!)
{
entries = MagicValueDatabaseEntry.GetEntries(str);
}
- AddMagicValues(entries.Select(x => (MagicValueMediaType)x));
+ AddMagicValues(entries);
}
public IReadOnlyCollection MediaTypes => _mediaTypes.AsReadOnly();
@@ -86,6 +84,8 @@ namespace ReMime.ContentResolvers
return _extensions.TryGetValue(extension, out mediaType);
}
+ public static MagicContentResolver Instance { get; } = new MagicContentResolver();
+
private class Tree
{
public MagicValueMediaType? Node { get; private set; }
diff --git a/ReMime/ContentResolvers/MagicValueDatabaseEntry.cs b/ReMime/ContentResolvers/MagicValueDatabaseEntry.cs
index bb5262d..f23924f 100644
--- a/ReMime/ContentResolvers/MagicValueDatabaseEntry.cs
+++ b/ReMime/ContentResolvers/MagicValueDatabaseEntry.cs
@@ -18,24 +18,24 @@ namespace ReMime.ContentResolvers
[JsonPropertyName("extensions")]
public List Extensions { get; set; } = new List();
- public static List GetEntries(Stream str)
+ public static IEnumerable GetEntries(Stream str)
{
return JsonSerializer.Deserialize>(str, new JsonSerializerOptions()
{
AllowTrailingCommas = true,
ReadCommentHandling = JsonCommentHandling.Skip
- }) ?? throw new Exception();
+ })?.Select(x => (MagicValueMediaType)x)
+ ?? throw new Exception();
}
public static explicit operator MagicValueMediaType(MagicValueDatabaseEntry entry)
{
return new MagicValueMediaType(
- new MediaType(entry.Type),
+ new MediaType(entry.Type, entry.Extensions),
entry.Magic.Select(x => (MagicValue.TryParse(x, out var value), value))
.Where(x => x.Item1)
.Select(x => (MagicValue)x.value!)
- .ToArray(),
- entry.Extensions.ToArray()
+ .ToArray()
);
}
}
diff --git a/ReMime/ContentResolvers/RiffResolver.cs b/ReMime/ContentResolvers/RiffResolver.cs
index ea949fe..85a0cb7 100644
--- a/ReMime/ContentResolvers/RiffResolver.cs
+++ b/ReMime/ContentResolvers/RiffResolver.cs
@@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
namespace ReMime.ContentResolvers
{
- public class RiffResolver : IMediaTypeResolver, IMediaContentResolver
+ public class RiffResolver : IMediaContentResolver, IMagicValueResolver
{
public readonly List _mediaTypes = new List();
public readonly Dictionary _extensions = new Dictionary();
@@ -15,27 +15,26 @@ namespace ReMime.ContentResolvers
public IReadOnlyCollection MediaTypes { get; }
- public RiffResolver()
+ private RiffResolver()
{
MediaTypes = _mediaTypes.AsReadOnly();
- List entries;
+ IEnumerable entries;
using (Stream str = typeof(MagicContentResolver).Assembly.GetManifestResourceStream("ReMime.ContentResolvers.riff.jsonc")!)
{
entries = MagicValueDatabaseEntry.GetEntries(str);
}
- foreach (var entry in entries)
- {
- AddRiffType((MagicValueMediaType)entry);
- }
+ AddMagicValues(entries);
}
- public RiffResolver(IEnumerable values) : this()
+ public void AddMagicValues(IEnumerable entries)
{
- foreach (MagicValueMediaType value in values)
- AddRiffType(value);
+ foreach (var entry in entries)
+ {
+ AddMagicValue(entry);
+ }
}
public bool TryResolve(Stream str, [NotNullWhen(true)] out MediaType? mediaType)
@@ -69,7 +68,7 @@ namespace ReMime.ContentResolvers
/// Add a RIFF sub-magic value to this resolver.
///
///
- public void AddRiffType(MagicValueMediaType type)
+ public void AddMagicValue(MagicValueMediaType type)
{
if (type.MagicValues.Length == 0)
throw new ArgumentException("Expected at least one media type.");
@@ -92,6 +91,8 @@ namespace ReMime.ContentResolvers
}
}
+ public static RiffResolver Instance { get; } = new RiffResolver();
+
[StructLayout(LayoutKind.Auto, Size = 12)]
private struct RiffChunk
{
diff --git a/ReMime/MediaTypeResolver.cs b/ReMime/MediaTypeResolver.cs
index e116737..5bff010 100644
--- a/ReMime/MediaTypeResolver.cs
+++ b/ReMime/MediaTypeResolver.cs
@@ -50,22 +50,13 @@ namespace ReMime
static MediaTypeResolver()
{
- AddResolver(new RiffResolver(), 9997);
- AddResolver(new MagicContentResolver(), 9998);
+ AddResolver(RiffResolver.Instance, 1000);
+ AddResolver(MagicContentResolver.Instance, 1001);
- if (OperatingSystem.IsWindows())
- {
- AddResolver(new Win32MediaTypeResolver());
- }
- else if (OperatingSystem.IsLinux())
- {
- AddResolver(new UnixMediaTypeResolver());
- // TODO: add freedesktop mime type database.
- }
- else if (OperatingSystem.IsMacOS())
- {
- AddResolver(new UnixMediaTypeResolver()); //?
- }
+ if (Win32MediaTypeResolver.Instance != null)
+ AddResolver(Win32MediaTypeResolver.Instance, 1002);
+ if (UnixMediaTypeResolver.Instance != null)
+ AddResolver(UnixMediaTypeResolver.Instance, 1002);
}
///
diff --git a/ReMime/Platform/UnixMediaTypeResolver.cs b/ReMime/Platform/UnixMediaTypeResolver.cs
index d50f7fb..3c1902f 100644
--- a/ReMime/Platform/UnixMediaTypeResolver.cs
+++ b/ReMime/Platform/UnixMediaTypeResolver.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Diagnostics;
using System.IO;
namespace ReMime.Platform
@@ -13,7 +14,7 @@ namespace ReMime.Platform
private readonly Dictionary _extensionsMap = new Dictionary();
public IReadOnlyCollection MediaTypes { get; }
- public UnixMediaTypeResolver()
+ private UnixMediaTypeResolver()
{
{
bool valid = OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsFreeBSD();
@@ -53,6 +54,20 @@ namespace ReMime.Platform
return _extensionsMap.TryGetValue(extension, out mediaType);
}
+ public static UnixMediaTypeResolver? Instance { get; } = null;
+
+ static UnixMediaTypeResolver()
+ {
+ try
+ {
+ Instance = new UnixMediaTypeResolver();
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
+ }
+ }
+
private static readonly char[] s_delimeters = new char[] { '\t', ' ' };
private static void DigestMimeDatabase(TextReader reader, List types)
diff --git a/ReMime/Platform/Win32MediaTypeResolver.cs b/ReMime/Platform/Win32MediaTypeResolver.cs
index 9cd0bfb..4daa635 100644
--- a/ReMime/Platform/Win32MediaTypeResolver.cs
+++ b/ReMime/Platform/Win32MediaTypeResolver.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using Microsoft.Win32;
@@ -13,7 +14,7 @@ namespace ReMime.Platform
private readonly Dictionary _extensionsMap = new Dictionary();
public IReadOnlyCollection MediaTypes { get; }
- public Win32MediaTypeResolver()
+ private Win32MediaTypeResolver()
{
if (!OperatingSystem.IsWindows())
throw new PlatformNotSupportedException();
@@ -57,5 +58,19 @@ namespace ReMime.Platform
{
return _extensionsMap.TryGetValue(extension, out mediaType);
}
+
+ public static Win32MediaTypeResolver? Instance { get; } = null;
+
+ static Win32MediaTypeResolver()
+ {
+ try
+ {
+ Instance = new Win32MediaTypeResolver();
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/ReMime/ReMime.csproj b/ReMime/ReMime.csproj
index 7c64d3f..78dcaa9 100644
--- a/ReMime/ReMime.csproj
+++ b/ReMime/ReMime.csproj
@@ -8,7 +8,7 @@
True
ReFuel.ReMime
- 0.1.0
+ 0.1.1
H. Utku Maden
ReFuel
README.md