using System.IO; using System.Linq; using System.Text; using SabreTools.IO.Writers; using SabreTools.Models.DosCenter; namespace SabreTools.Serialization { /// /// Deserializer for DosCenter metadata files /// public partial class DosCenter { /// /// Serializes the defined type to a DosCenter metadata file /// /// Data to serialize /// Path to the file to serialize to /// True on successful serialization, false otherwise public static bool SerializeToFile(MetadataFile? metadataFile, string path) { using var stream = SerializeToStream(metadataFile); if (stream == null) return false; using var fs = System.IO.File.OpenWrite(path); stream.CopyTo(fs); return true; } /// /// Serializes the defined type to a stream /// /// Data to serialize /// Stream containing serialized data on success, null otherwise public static Stream? SerializeToStream(MetadataFile? metadataFile) { // If the metadata file is null if (metadataFile == null) return null; // Setup the writer and output var stream = new MemoryStream(); var writer = new ClrMameProWriter(stream, Encoding.UTF8) { Quotes = false, }; // Write the header, if it exists WriteHeader(metadataFile.DosCenter, writer); // Write out the games, if they exist WriteGames(metadataFile.Game, writer); // Return the stream stream.Seek(0, SeekOrigin.Begin); return stream; } /// /// Write header information to the current writer /// /// DosCenter representing the header information /// ClrMameProWriter representing the output private static void WriteHeader(Models.DosCenter.DosCenter? header, ClrMameProWriter writer) { // If the header information is missing, we can't do anything if (header == null) return; writer.WriteStartElement("DOSCenter"); writer.WriteOptionalStandalone("Name:", header.Name); writer.WriteOptionalStandalone("Description:", header.Description); writer.WriteOptionalStandalone("Version:", header.Version); writer.WriteOptionalStandalone("Date:", header.Date); writer.WriteOptionalStandalone("Author:", header.Author); writer.WriteOptionalStandalone("Homepage:", header.Homepage); writer.WriteOptionalStandalone("Comment:", header.Comment); writer.WriteEndElement(); // doscenter writer.Flush(); } /// /// Write games information to the current writer /// /// Array of Game objects representing the games information /// ClrMameProWriter representing the output private static void WriteGames(Game[]? games, ClrMameProWriter writer) { // If the games information is missing, we can't do anything if (games == null || !games.Any()) return; // Loop through and write out the games foreach (var game in games) { WriteGame(game, writer); writer.Flush(); } } /// /// Write game information to the current writer /// /// Game object representing the game information /// ClrMameProWriter representing the output private static void WriteGame(Game game, ClrMameProWriter writer) { // If the game information is missing, we can't do anything if (game == null) return; writer.WriteStartElement("game"); // Write the standalone values writer.WriteRequiredStandalone("name", game.Name, throwOnError: true); // Write the item values WriteFiles(game.File, writer); writer.WriteEndElement(); // game } /// /// Write files information to the current writer /// /// Array of File objects to write /// ClrMameProWriter representing the output private static void WriteFiles(Models.DosCenter.File[]? files, ClrMameProWriter writer) { // If the array is missing, we can't do anything if (files == null) return; foreach (var file in files) { writer.WriteStartElement("file"); writer.WriteRequiredAttributeString("name", file.Name, throwOnError: true); writer.WriteRequiredAttributeString("size", file.Size, throwOnError: true); writer.WriteOptionalAttributeString("date", file.Date); writer.WriteRequiredAttributeString("crc", file.CRC?.ToUpperInvariant(), throwOnError: true); writer.WriteEndElement(); // file } } #region Internal /// /// Convert from to /// public static Models.Metadata.MetadataFile? ConvertToInternalModel(MetadataFile? item) { if (item == null) return null; var metadataFile = new Models.Metadata.MetadataFile(); if (item?.DosCenter != null) metadataFile[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(item.DosCenter); if (item?.Game != null && item.Game.Any()) { metadataFile[Models.Metadata.MetadataFile.MachineKey] = item.Game .Where(g => g != null) .Select(ConvertMachineToInternalModel) .ToArray(); } return metadataFile; } /// /// Convert from to /// private static Models.Metadata.Header ConvertHeaderToInternalModel(Models.DosCenter.DosCenter item) { var header = new Models.Metadata.Header { [Models.Metadata.Header.NameKey] = item.Name, [Models.Metadata.Header.DescriptionKey] = item.Description, [Models.Metadata.Header.VersionKey] = item.Version, [Models.Metadata.Header.DateKey] = item.Date, [Models.Metadata.Header.AuthorKey] = item.Author, [Models.Metadata.Header.HomepageKey] = item.Homepage, [Models.Metadata.Header.CommentKey] = item.Comment, }; return header; } /// /// Convert from to /// private static Models.Metadata.Machine ConvertMachineToInternalModel(Game item) { var machine = new Models.Metadata.Machine { [Models.Metadata.Machine.NameKey] = item.Name, }; if (item.File != null && item.File.Any()) { machine[Models.Metadata.Machine.RomKey] = item.File .Where(f => f != null) .Select(ConvertToInternalModel) .ToArray(); } return machine; } /// /// Convert from to /// private static Models.Metadata.Rom ConvertToInternalModel(Models.DosCenter.File item) { var rom = new Models.Metadata.Rom { [Models.Metadata.Rom.NameKey] = item.Name, [Models.Metadata.Rom.SizeKey] = item.Size, [Models.Metadata.Rom.CRCKey] = item.CRC, [Models.Metadata.Rom.DateKey] = item.Date, }; return rom; } #endregion } }