internal static RantResource DeserializeResource(EasyReader reader) { var typeCode = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (!_resourceTypeRegistry.TryGetValue(typeCode, out Type type)) { throw new InvalidDataException($"Unrecognized resource type: '{typeCode}'"); } var resource = Activator.CreateInstance(type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new object[0], null) as RantResource; resource?.DeserializeData(reader); return(resource); }
/// <summary> /// Loads a compiled Rant program from the specified stream. /// </summary> /// <param name="programName">The name to give to the program.</param> /// <param name="stream">The stream to load the program from.</param> /// <returns></returns> public static RantProgram LoadStream(string programName, Stream stream) { if (programName == null) { throw new ArgumentNullException(nameof(programName)); } if (stream == null) { throw new ArgumentNullException(nameof(stream)); } using (var input = new EasyReader(stream)) { if (Encoding.ASCII.GetString(input.ReadBytes(4)) != Magic) { throw new InvalidDataException(GetString("err-pgmload-bad-magic")); } var rst = RST.DeserializeRST(input); // TODO: Use string table return(new RantProgram(programName, RantProgramOrigin.File, rst)); } }
/// <summary> /// Loads a package from the specified stream and returns it as a RantPackage object. /// </summary> /// <param name="source">The stream to load the package data from.</param> /// <returns></returns> public static RantPackage Load(Stream source) { using (var reader = new EasyReader(source)) { string magic = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (magic != MAGIC) { throw new InvalidDataException(GetString("err-file-corrupt")); } ushort version = reader.ReadUInt16(); if (version != PACKAGE_FORMAT_VERSION) { throw new InvalidDataException(GetString("err-invalid-package-version", version)); } bool compress = reader.ReadBoolean(); var package = new RantPackage(); package.Title = reader.ReadString(); package.ID = reader.ReadString(); package.Description = reader.ReadString(); package.Tags = reader.ReadStringArray(); package.Authors = reader.ReadStringArray(); int vmaj = reader.ReadInt32(); int vmin = reader.ReadInt32(); int vrev = reader.ReadInt32(); package.Version = new RantPackageVersion(vmaj, vmin, vrev); int depCount = reader.ReadInt32(); for (int i = 0; i < depCount; i++) { var depId = reader.ReadString(); int depVerMaj = reader.ReadInt32(); int depVerMin = reader.ReadInt32(); int depVerRev = reader.ReadInt32(); bool depAllowNewer = reader.ReadBoolean(); package.AddDependency(new RantPackageDependency(depId, new RantPackageVersion(depVerMaj, depVerMin, depVerRev)) { AllowNewer = depAllowNewer }); } int resCount = reader.ReadInt32(); if (compress) { using (var decompressStream = new DeflateStream(reader.BaseStream, CompressionMode.Decompress, true)) { for (int i = 0; i < resCount; i++) { package._resources.Add(RantResource.DeserializeResource(new EasyReader(decompressStream, true))); } } } else { for (int i = 0; i < resCount; i++) { package._resources.Add(RantResource.DeserializeResource(reader)); } } return(package); } }
/// <summary> /// Loads a package from the specified stream and returns it as a RantPackage object. /// </summary> /// <param name="source">The stream to load the package data from.</param> /// <returns></returns> public static RantPackage Load(Stream source) { using (var reader = new EasyReader(source)) { if (Encoding.ASCII.GetString(reader.ReadBytes(4)) != Magic) throw new InvalidDataException("File is corrupt."); int numPatterns = reader.ReadInt32(); int numTables = reader.ReadInt32(); if (numPatterns < 0 || numTables < 0) throw new InvalidDataException("File is corrupt."); var pkg = new RantPackage(); // Patterns for (int i = 0; i < numPatterns; i++) { var name = reader.ReadString(); var code = reader.ReadString(); pkg.AddPattern(new RantPattern(name, RantPatternSource.String, code)); } // Tables for (int i = 0; i < numTables; i++) { var name = reader.ReadString(); var subs = reader.ReadStringArray(); int numEntries = reader.ReadInt32(); var hiddenClasses = reader.ReadStringArray(); var entries = new RantDictionaryEntry[numEntries]; for (int j = 0; j < numEntries; j++) { int weight = reader.ReadInt32(); bool flags = reader.ReadBoolean(); // unused int numTerms = reader.ReadInt32(); var terms = new RantDictionaryTerm[numTerms]; for (int k = 0; k < numTerms; k++) { var value = reader.ReadString(); var pron = reader.ReadString(); terms[k] = new RantDictionaryTerm(value, pron); } var classes = reader.ReadStringArray(); entries[j] = new RantDictionaryEntry(terms, classes, weight); } pkg.AddTable(new RantDictionaryTable(name, subs, entries, hiddenClasses)); } return pkg; } }
private static BsonItem ReadItem(byte code, BsonDocument document, EasyReader reader) { object val = null; switch (code) { case 0x01: // double val = reader.ReadDouble(); break; case 0x02: // string val = reader.ReadString(Encoding.UTF8).TrimEnd('\x00'); if (document.StringTableMode == BsonStringTableMode.KeysAndValues) val = document.ReverseStringTable[int.Parse((string)val)]; break; case 0x03: // document val = Read(reader, document).Top; break; case 0x04: // array val = Read(reader, document, true).Top; break; case 0x05: // binary var length = reader.ReadInt32(); var subtype = reader.ReadByte(); if (subtype != 0x00) throw new NotSupportedException("BSON subtypes other than 'generic binary data' are not supported."); val = reader.ReadBytes(length); break; case 0x06: // undefined break; case 0x07: // ObjectId // why does this parser support ObjectIds and not other binary data? // shhhhh val = Encoding.ASCII.GetString(reader.ReadBytes(12)); break; case 0x08: // boolean val = reader.ReadBoolean(); break; case 0x09: // UTC datetime val = reader.ReadInt64(); break; case 0x0A: // null break; case 0x0B: // regex // why are you using regex in a Rant package? throw new NotSupportedException("Regular expressions are not supported."); case 0x0C: // db pointer throw new NotSupportedException("DB pointers are not supported."); case 0x0D: // Javascript code case 0x0F: // JS code with scope throw new NotSupportedException("Javascript in BSON is not supported."); case 0x0E: // depreceated val = reader.ReadString(Encoding.UTF8); break; case 0x10: // 32 bit integer val = reader.ReadInt32(); break; case 0x11: // timestamp case 0x12: // 64 bit integer val = reader.ReadInt64(); break; case 0xFF: // min key case 0x7F: // max key // we don't care about these so let's just skip em break; } if (!(val is BsonItem)) return new BsonItem(val) { Type = code }; var i = (BsonItem)val; i.Type = code; return i; }
/// <summary> /// Loads a package from the specified stream and returns it as a RantPackage object. /// </summary> /// <param name="source">The stream to load the package data from.</param> /// <returns></returns> public static RantPackage Load(Stream source) { using (var reader = new EasyReader(source)) { var magic = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (magic == OLD_MAGIC) { return(LoadOldPackage(reader)); } if (magic != MAGIC) { throw new InvalidDataException("File is corrupt."); } var package = new RantPackage(); var version = reader.ReadUInt32(); if (version != PACKAGE_VERSION) { throw new InvalidDataException("Invalid package version: " + version); } var compress = reader.ReadBoolean(); var size = reader.ReadInt32(); var data = reader.ReadBytes(size); if (compress) { data = EasyCompressor.Decompress(data); } var doc = BsonDocument.Read(data); var info = doc["info"]; if (info == null) { throw new InvalidDataException("Metadata is missing from package."); } package.Title = info["title"]; package.ID = info["id"]; package.Version = RantPackageVersion.Parse(info["version"]); package.Description = info["description"]; package.Authors = (string[])info["authors"]; package.Tags = (string[])info["tags"]; var deps = info["dependencies"]; if (deps != null && deps.IsArray) { for (int i = 0; i < deps.Count; i++) { var dep = deps[i]; var depId = dep["id"].Value; var depVersion = dep["version"].Value; bool depAllowNewer = (bool)dep["allow-newer"].Value; package.AddDependency(new RantPackageDependency(depId.ToString(), depVersion.ToString()) { AllowNewer = depAllowNewer }); } } var patterns = doc["patterns"]; if (patterns != null) { var names = patterns.Keys; foreach (string name in names) { package.AddPattern(new RantPattern(name, RantPatternOrigin.File, patterns[name])); } } var tables = doc["tables"]; if (tables != null) { var names = tables.Keys; foreach (string name in names) { var table = tables[name]; string tableName = table["name"]; string[] tableSubs = (string[])table["subs"]; string[] hiddenClasses = (string[])table["hidden"]; var entries = new List <RantDictionaryEntry>(); var entryList = table["entries"]; for (var i = 0; i < entryList.Count; i++) { var loadedEntry = entryList[i]; int weight = 1; if (loadedEntry.HasKey("weight")) { weight = (int)loadedEntry["weight"].Value; } string[] requiredClasses = (string[])loadedEntry["classes"]; string[] optionalClasses = (string[])loadedEntry["optional_classes"]; var terms = new List <RantDictionaryTerm>(); var termList = loadedEntry["terms"]; for (var j = 0; j < termList.Count; j++) { var t = new RantDictionaryTerm(termList[j]["value"], termList[j]["pron"]); terms.Add(t); } var entry = new RantDictionaryEntry( terms.ToArray(), requiredClasses.Concat(optionalClasses.Select(x => x + "?")), weight ); entries.Add(entry); } var rantTable = new RantDictionaryTable( tableName, tableSubs, entries, hiddenClasses ); package.AddTable(rantTable); } } return(package); } }
private static BsonItem ReadItem(byte code, BsonDocument document, EasyReader reader) { object val = null; switch (code) { case 0x01: // double val = reader.ReadDouble(); break; case 0x02: // string val = reader.ReadString(Encoding.UTF8).TrimEnd('\x00'); if (document.StringTableMode == BsonStringTableMode.KeysAndValues) { val = document.ReverseStringTable[int.Parse((string)val)]; } break; case 0x03: // document val = Read(reader, document).Top; break; case 0x04: // array val = Read(reader, document, true).Top; break; case 0x05: // binary var length = reader.ReadInt32(); var subtype = reader.ReadByte(); if (subtype != 0x00) { throw new NotSupportedException("BSON subtypes other than 'generic binary data' are not supported."); } val = reader.ReadBytes(length); break; case 0x06: // undefined break; case 0x07: // ObjectId // why does this parser support ObjectIds and not other binary data? // shhhhh val = Encoding.ASCII.GetString(reader.ReadBytes(12)); break; case 0x08: // boolean val = reader.ReadBoolean(); break; case 0x09: // UTC datetime val = reader.ReadInt64(); break; case 0x0A: // null break; case 0x0B: // regex // why are you using regex in a Rant package? throw new NotSupportedException("Regular expressions are not supported."); case 0x0C: // db pointer throw new NotSupportedException("DB pointers are not supported."); case 0x0D: // Javascript code case 0x0F: // JS code with scope throw new NotSupportedException("Javascript in BSON is not supported."); case 0x0E: // depreceated val = reader.ReadString(Encoding.UTF8); break; case 0x10: // 32 bit integer val = reader.ReadInt32(); break; case 0x11: // timestamp case 0x12: // 64 bit integer val = reader.ReadInt64(); break; case 0xFF: // min key case 0x7F: // max key // we don't care about these so let's just skip em break; } if (!(val is BsonItem)) { return new BsonItem(val) { Type = code } } ; var i = (BsonItem)val; i.Type = code; return(i); } }
/// <summary> /// Loads a package from the specified stream and returns it as a RantPackage object. /// </summary> /// <param name="source">The stream to load the package data from.</param> /// <returns></returns> public static RantPackage Load(Stream source) { using (var reader = new EasyReader(source)) { var magic = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (magic == OLD_MAGIC) return LoadOldPackage(reader); if (magic != MAGIC) throw new InvalidDataException("File is corrupt."); var package = new RantPackage(); var version = reader.ReadUInt32(); if (version != PACKAGE_VERSION) throw new InvalidDataException("Invalid package version: " + version); var compress = reader.ReadBoolean(); var size = reader.ReadInt32(); var data = reader.ReadBytes(size); if (compress) data = EasyCompressor.Decompress(data); var doc = BsonDocument.Read(data); var info = doc["info"]; if (info == null) throw new InvalidDataException("Metadata is missing from package."); package.Title = info["title"]; package.ID = info["id"]; package.Version = RantPackageVersion.Parse(info["version"]); package.Description = info["description"]; package.Authors = (string[])info["authors"]; package.Tags = (string[])info["tags"]; var deps = info["dependencies"]; if (deps != null && deps.IsArray) { for(int i = 0; i < deps.Count; i++) { var dep = deps[i]; var depId = dep["id"].Value; var depVersion = dep["version"].Value; bool depAllowNewer = (bool)dep["allow-newer"].Value; package.AddDependency(new RantPackageDependency(depId.ToString(), depVersion.ToString()) { AllowNewer = depAllowNewer }); } } var patterns = doc["patterns"]; if(patterns != null) { var names = patterns.Keys; foreach (string name in names) package.AddPattern(new RantPattern(name, RantPatternOrigin.File, patterns[name])); } var tables = doc["tables"]; if(tables != null) { var names = tables.Keys; foreach(string name in names) { var table = tables[name]; string tableName = table["name"]; string[] tableSubs = (string[])table["subs"]; string[] hiddenClasses = (string[])table["hidden"]; var entries = new List<RantDictionaryEntry>(); var entryList = table["entries"]; for(var i = 0; i < entryList.Count; i++) { var loadedEntry = entryList[i]; int weight = 1; if (loadedEntry.HasKey("weight")) weight = (int)loadedEntry["weight"].Value; string[] requiredClasses = (string[])loadedEntry["classes"]; string[] optionalClasses = (string[])loadedEntry["optional_classes"]; var terms = new List<RantDictionaryTerm>(); var termList = loadedEntry["terms"]; for(var j = 0; j < termList.Count; j++) { var t = new RantDictionaryTerm(termList[j]["value"], termList[j]["pron"]); terms.Add(t); } var entry = new RantDictionaryEntry( terms.ToArray(), requiredClasses.Concat(optionalClasses.Select(x => x + "?")), weight ); entries.Add(entry); } var rantTable = new RantDictionaryTable( tableName, tableSubs, entries, hiddenClasses ); package.AddTable(rantTable); } } return package; } }