using System; using System.IO; using System.Text; using SabreTools.Data.Models.Hashfile; using SabreTools.Hashing; using SabreTools.IO.Extensions; using SabreTools.Text.SeparatedValue; #pragma warning disable CA1822 // Mark members as static namespace SabreTools.Serialization.Writers { public class Hashfile : BaseBinaryWriter { #region IByteWriter /// public override byte[]? SerializeArray(Data.Models.Hashfile.Hashfile? obj) => SerializeArray(obj, HashType.CRC32); /// public byte[]? SerializeArray(Data.Models.Hashfile.Hashfile? obj, HashType hash) { using var stream = SerializeStream(obj, hash); if (stream is null) return null; byte[] bytes = new byte[stream.Length]; int read = stream.Read(bytes, 0, bytes.Length); return bytes; } #endregion #region IFileWriter /// public override bool SerializeFile(Data.Models.Hashfile.Hashfile? obj, string? path) => SerializeFile(obj, path, HashType.CRC32); /// public bool SerializeFile(Data.Models.Hashfile.Hashfile? obj, string? path, HashType hash) { if (string.IsNullOrEmpty(path)) return false; using var stream = SerializeStream(obj, hash); if (stream is null) return false; using var fs = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.None); stream.BlockCopy(fs); fs.Flush(); return true; } #endregion #region IStreamWriter /// public override Stream? SerializeStream(Data.Models.Hashfile.Hashfile? obj) => SerializeStream(obj, HashType.CRC32); /// public Stream? SerializeStream(Data.Models.Hashfile.Hashfile? obj, HashType hash) { // If the metadata file is null if (obj is null) return null; // Setup the writer and output var stream = new MemoryStream(); var writer = new Writer(stream, Encoding.UTF8) { Separator = ' ', Quotes = false, VerifyFieldCount = false, }; // Write out the items, if they exist if (hash == HashType.CRC32) WriteSFV(obj.SFV, writer); else if (hash == HashType.MD2) WriteMD2(obj.MD2, writer); else if (hash == HashType.MD4) WriteMD4(obj.MD4, writer); else if (hash == HashType.MD5) WriteMD5(obj.MD5, writer); else if (hash == HashType.RIPEMD128) WriteRIPEMD128(obj.RIPEMD128, writer); else if (hash == HashType.RIPEMD160) WriteRIPEMD160(obj.RIPEMD160, writer); else if (hash == HashType.SHA1) WriteSHA1(obj.SHA1, writer); else if (hash == HashType.SHA256) WriteSHA256(obj.SHA256, writer); else if (hash == HashType.SHA384) WriteSHA384(obj.SHA384, writer); else if (hash == HashType.SHA512) WriteSHA512(obj.SHA512, writer); else if (hash == HashType.SpamSum) WriteSpamSum(obj.SpamSum, writer); else throw new ArgumentOutOfRangeException(nameof(hash)); // Return the stream stream.SeekIfPossible(0, SeekOrigin.Begin); return stream; } /// /// Write SFV information to the current writer /// /// Array of SFV objects representing the files /// Writer representing the output private static void WriteSFV(SFV[]? sfvs, Writer writer) { // If the item information is missing, we can't do anything if (sfvs is null || sfvs.Length == 0) return; // Loop through and write out the items foreach (var sfv in sfvs) { if (string.IsNullOrEmpty(sfv.File) || string.IsNullOrEmpty(sfv.Hash)) continue; writer.WriteValues([sfv.File!, sfv.Hash!]); writer.Flush(); } } /// /// Write MD2 information to the current writer /// /// Array of MD2 objects representing the files /// Writer representing the output private static void WriteMD2(MD2[]? md2s, Writer writer) { // If the item information is missing, we can't do anything if (md2s is null || md2s.Length == 0) return; // Loop through and write out the items foreach (var md2 in md2s) { if (string.IsNullOrEmpty(md2.Hash) || string.IsNullOrEmpty(md2.File)) continue; writer.WriteValues([md2.Hash!, md2.File!]); writer.Flush(); } } /// /// Write MD4 information to the current writer /// /// Array of MD4 objects representing the files /// Writer representing the output private static void WriteMD4(MD4[]? md4s, Writer writer) { // If the item information is missing, we can't do anything if (md4s is null || md4s.Length == 0) return; // Loop through and write out the items foreach (var md4 in md4s) { if (string.IsNullOrEmpty(md4.Hash) || string.IsNullOrEmpty(md4.File)) continue; writer.WriteValues([md4.Hash!, md4.File!]); writer.Flush(); } } /// /// Write MD5 information to the current writer /// /// Array of MD5 objects representing the files /// Writer representing the output private static void WriteMD5(MD5[]? md5s, Writer writer) { // If the item information is missing, we can't do anything if (md5s is null || md5s.Length == 0) return; // Loop through and write out the items foreach (var md5 in md5s) { if (string.IsNullOrEmpty(md5.Hash) || string.IsNullOrEmpty(md5.File)) continue; writer.WriteValues([md5.Hash!, md5.File!]); writer.Flush(); } } /// /// Write RIPEMD128 information to the current writer /// /// Array of RIPEMD128 objects representing the files /// Writer representing the output private static void WriteRIPEMD128(RIPEMD128[]? ripemd128s, Writer writer) { // If the item information is missing, we can't do anything if (ripemd128s is null || ripemd128s.Length == 0) return; // Loop through and write out the items foreach (var ripemd128 in ripemd128s) { if (string.IsNullOrEmpty(ripemd128.Hash) || string.IsNullOrEmpty(ripemd128.File)) continue; writer.WriteValues([ripemd128.Hash!, ripemd128.File!]); writer.Flush(); } } /// /// Write RIPEMD160 information to the current writer /// /// Array of RIPEMD160 objects representing the files /// Writer representing the output private static void WriteRIPEMD160(RIPEMD160[]? ripemd160s, Writer writer) { // If the item information is missing, we can't do anything if (ripemd160s is null || ripemd160s.Length == 0) return; // Loop through and write out the items foreach (var ripemd160 in ripemd160s) { if (string.IsNullOrEmpty(ripemd160.Hash) || string.IsNullOrEmpty(ripemd160.File)) continue; writer.WriteValues([ripemd160.Hash!, ripemd160.File!]); writer.Flush(); } } /// /// Write SHA1 information to the current writer /// /// Array of SHA1 objects representing the files /// Writer representing the output private static void WriteSHA1(SHA1[]? sha1s, Writer writer) { // If the item information is missing, we can't do anything if (sha1s is null || sha1s.Length == 0) return; // Loop through and write out the items foreach (var sha1 in sha1s) { if (string.IsNullOrEmpty(sha1.Hash) || string.IsNullOrEmpty(sha1.File)) continue; writer.WriteValues([sha1.Hash!, sha1.File!]); writer.Flush(); } } /// /// Write SHA256 information to the current writer /// /// Array of SHA256 objects representing the files /// Writer representing the output private static void WriteSHA256(SHA256[]? sha256s, Writer writer) { // If the item information is missing, we can't do anything if (sha256s is null || sha256s.Length == 0) return; // Loop through and write out the items foreach (var sha256 in sha256s) { if (string.IsNullOrEmpty(sha256.Hash) || string.IsNullOrEmpty(sha256.File)) continue; writer.WriteValues([sha256.Hash!, sha256.File!]); writer.Flush(); } } /// /// Write SHA384 information to the current writer /// /// Array of SHA384 objects representing the files /// Writer representing the output private static void WriteSHA384(SHA384[]? sha384s, Writer writer) { // If the item information is missing, we can't do anything if (sha384s is null || sha384s.Length == 0) return; // Loop through and write out the items foreach (var sha384 in sha384s) { if (string.IsNullOrEmpty(sha384.Hash) || string.IsNullOrEmpty(sha384.File)) continue; writer.WriteValues([sha384.Hash!, sha384.File!]); writer.Flush(); } } /// /// Write SHA512 information to the current writer /// /// Array of SHA512 objects representing the files /// Writer representing the output private static void WriteSHA512(SHA512[]? sha512s, Writer writer) { // If the item information is missing, we can't do anything if (sha512s is null || sha512s.Length == 0) return; // Loop through and write out the items foreach (var sha512 in sha512s) { if (string.IsNullOrEmpty(sha512.Hash) || string.IsNullOrEmpty(sha512.File)) continue; writer.WriteValues([sha512.Hash!, sha512.File!]); writer.Flush(); } } /// /// Write SpamSum information to the current writer /// /// Array of SpamSum objects representing the files /// Writer representing the output private static void WriteSpamSum(SpamSum[]? spamsums, Writer writer) { // If the item information is missing, we can't do anything if (spamsums is null || spamsums.Length == 0) return; // Loop through and write out the items foreach (var spamsum in spamsums) { if (string.IsNullOrEmpty(spamsum.Hash) || string.IsNullOrEmpty(spamsum.File)) continue; writer.WriteValues([spamsum.Hash!, spamsum.File!]); writer.Flush(); } } #endregion } }