wabbajack/Wabbajack.Common/FileSignatures/SignatureChecker.cs

48 lines
1.5 KiB
C#
Raw Normal View History

using System.Collections.Generic;
2020-09-04 21:00:29 +00:00
using System.IO;
using System.Linq;
using System.Threading.Tasks;
2021-09-27 12:42:46 +00:00
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
namespace Wabbajack.Common.FileSignatures
{
public class SignatureChecker
{
private readonly int _maxLength;
2021-09-27 12:42:46 +00:00
private readonly (FileType, byte[])[] _signatures;
2021-09-27 12:42:46 +00:00
public SignatureChecker(params FileType[] types)
{
2021-09-27 12:42:46 +00:00
HashSet<FileType> types1 = new(types);
_signatures = Definitions.Signatures.Where(row => types1.Contains(row.Item1))
.OrderByDescending(x => x.Item2.Length).ToArray();
_maxLength = _signatures.First().Item2.Length;
}
2021-09-27 12:42:46 +00:00
public async ValueTask<FileType?> MatchesAsync(AbsolutePath path)
{
2021-09-27 12:42:46 +00:00
await using var fs = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
2020-09-04 21:00:29 +00:00
return await MatchesAsync(fs);
}
2021-09-27 12:42:46 +00:00
public async ValueTask<FileType?> MatchesAsync(Stream stream)
2020-09-04 21:00:29 +00:00
{
var buffer = new byte[_maxLength];
2020-09-04 21:00:29 +00:00
stream.Position = 0;
await stream.ReadAsync(buffer);
2021-09-27 12:42:46 +00:00
stream.Position = 0;
foreach (var (fileType, signature) in _signatures)
if (AreEqual(buffer, signature))
return fileType;
return null;
}
private static bool AreEqual(IReadOnlyList<byte> a, IEnumerable<byte> b)
{
return !b.Where((t, i) => a[i] != t).Any();
}
}
2021-09-27 12:42:46 +00:00
}