public object Deserialize(EventReader reader, Type type) { if (reader == null) { throw new ArgumentNullException("reader"); } if (type == null) { throw new ArgumentNullException("type"); } bool flag = reader.Allow <StreamStart>() != null; bool flag2 = reader.Allow <DocumentStart>() != null; object obj2 = null; if (!reader.Accept <DocumentEnd>() && !reader.Accept <StreamEnd>()) { using (SerializerState state = new SerializerState()) { obj2 = this.valueDeserializer.DeserializeValue(reader, type, state, this.valueDeserializer); state.OnDeserialization(); } } if (flag2) { reader.Expect <DocumentEnd>(); } if (flag) { reader.Expect <StreamEnd>(); } return(obj2); }
/// <summary> /// Deserializes an object of the specified type. /// </summary> /// <param name="reader">The <see cref="EventReader" /> where to deserialize the object.</param> /// <param name="type">The static type of the object to deserialize.</param> /// <param name="options">Options that control how the deserialization is to be performed.</param> /// <returns>Returns the deserialized object.</returns> public object Deserialize(EventReader reader, Type type, DeserializationFlags options = DeserializationFlags.None) { if (reader == null) { throw new ArgumentNullException("reader"); } if (type == null) { throw new ArgumentNullException("type"); } var hasStreamStart = reader.Allow <StreamStart>() != null; var hasDocumentStart = reader.Allow <DocumentStart>() != null; object result = DeserializeValue(reader, type, null); if (hasDocumentStart) { reader.Expect <DocumentEnd>(); } if (hasStreamStart) { reader.Expect <StreamEnd>(); } return(result); }
/// <summary> /// Deserializes an object from the specified <see cref="EventReader" /> with an expected specific type. /// </summary> /// <param name="reader">The reader.</param> /// <param name="expectedType">The expected type, maybe null.</param> /// <param name="existingObject">An existing object, may be null.</param> /// <param name="contextSettings">The context settings.</param> /// <param name="context">The context used to deserialize the object.</param> /// <returns>A deserialized object.</returns> /// <exception cref="System.ArgumentNullException">reader</exception> public object Deserialize(EventReader reader, Type expectedType, object existingObject, SerializerContextSettings contextSettings, out SerializerContext context) { if (reader == null) { throw new ArgumentNullException("reader"); } var hasStreamStart = reader.Allow <StreamStart>() != null; var hasDocumentStart = reader.Allow <DocumentStart>() != null; context = null; object result = null; if (!reader.Accept <DocumentEnd>() && !reader.Accept <StreamEnd>()) { context = new SerializerContext(this, contextSettings) { Reader = reader }; result = context.ReadYaml(existingObject, expectedType); } if (hasDocumentStart) { reader.Expect <DocumentEnd>(); } if (hasStreamStart) { reader.Expect <StreamEnd>(); } return(result); }
/// <summary> /// Deserializes an object of the specified type. /// </summary> /// <param name="reader">The <see cref="EventReader" /> where to deserialize the object.</param> /// <param name="type">The static type of the object to deserialize.</param> /// <param name="options">Options that control how the deserialization is to be performed.</param> /// <returns>Returns the deserialized object.</returns> public object Deserialize(EventReader reader, Type type) { if (reader == null) { throw new ArgumentNullException("reader"); } if (type == null) { throw new ArgumentNullException("type"); } var hasStreamStart = reader.Allow <StreamStart>() != null; var hasDocumentStart = reader.Allow <DocumentStart>() != null; object result = null; if (!reader.Accept <DocumentEnd>() && !reader.Accept <StreamEnd>()) { result = valueDeserializer.DeserializeValue(reader, type, new SerializerState(), valueDeserializer); } if (hasDocumentStart) { reader.Expect <DocumentEnd>(); } if (hasStreamStart) { reader.Expect <StreamEnd>(); } return(result); }
public static YamlDocument Load(EventReader eventReader, YamlNodeTracker tracker = null) { var documentStart = eventReader.Allow <DocumentStart>(); var contents = ReadElement(eventReader, tracker); var documentEnd = eventReader.Allow <DocumentEnd>(); return(new YamlDocument(documentStart, documentEnd, contents, tracker)); }
/// <summary> /// Deserializes an object from the specified <see cref="EventReader" /> with an expected specific type. /// </summary> /// <param name="reader">The reader.</param> /// <param name="expectedType">The expected type, maybe null.</param> /// <param name="existingObject">An existing object, may be null.</param> /// <param name="contextSettings">The context settings.</param> /// <param name="context">The context used to deserialize the object.</param> /// <returns>A deserialized object.</returns> /// <exception cref="System.ArgumentNullException">reader</exception> public object Deserialize(EventReader reader, Type expectedType, object existingObject, SerializerContextSettings contextSettings, out SerializerContext context) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var hasStreamStart = reader.Allow <StreamStart>() != null; var hasDocumentStart = reader.Allow <DocumentStart>() != null; context = null; object result = null; if (!reader.Accept <DocumentEnd>() && !reader.Accept <StreamEnd>()) { context = new SerializerContext(this, contextSettings) { Reader = reader }; var node = context.Reader.Parser.Current; try { var objectContext = new ObjectContext(context, existingObject, context.FindTypeDescriptor(expectedType)); result = context.Serializer.ObjectSerializer.ReadYaml(ref objectContext); } catch (YamlException) { throw; } catch (Exception ex) { ex = ex.Unwrap(); throw new YamlException(node, ex); } } if (hasDocumentStart) { reader.Expect <DocumentEnd>(); } if (hasStreamStart) { reader.Expect <StreamEnd>(); } return(result); }
public static YamlStream Load(EventReader eventReader, YamlNodeTracker tracker = null) { var streamStart = eventReader.Allow <StreamStart>(); var documents = new List <YamlDocument>(); while (!eventReader.Accept <StreamEnd>()) { documents.Add(YamlDocument.Load(eventReader, tracker)); } var streamEnd = eventReader.Allow <StreamEnd>(); return(new YamlStream(streamStart, streamEnd, documents, tracker)); }
public void DeserializeManyDocuments() { var yaml = @"--- Name: Andy --- Name: Brad --- Name: Charles ..."; var serializer = new Serializer(); var reader = new EventReader(new Parser(new StringReader(yaml))); reader.Allow <StreamStart>(); var people = new List <Person>(); while (!reader.Accept <StreamEnd>()) { var person = serializer.Deserialize <Person>(reader); people.Add(person); } Assert.AreEqual(3, people.Count); Assert.AreEqual("Andy", people[0].Name); Assert.AreEqual("Brad", people[1].Name); Assert.AreEqual("Charles", people[2].Name); }
bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func <EventReader, Type, object> nestedObjectDeserializer, out object value) { if (reader.Allow <MappingStart>() == null) { value = null; return(false); } value = this._objectFactory.Create(expectedType); while (!reader.Accept <MappingEnd>()) {
public object DeserializeValue(EventReader reader, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer) { object value; var alias = reader.Allow <AnchorAlias>(); if (alias != null) { var aliasState = state.Get <AliasState>(); ValuePromise valuePromise; if (!aliasState.TryGetValue(alias.Value, out valuePromise)) { valuePromise = new ValuePromise(alias); aliasState.Add(alias.Value, valuePromise); } return(valuePromise.HasValue ? valuePromise.Value : valuePromise); } string anchor = null; var nodeEvent = reader.Peek <NodeEvent>(); if (nodeEvent != null && !string.IsNullOrEmpty(nodeEvent.Anchor)) { anchor = nodeEvent.Anchor; } value = innerDeserializer.DeserializeValue(reader, expectedType, state, nestedObjectDeserializer); if (anchor != null) { var aliasState = state.Get <AliasState>(); ValuePromise valuePromise; if (!aliasState.TryGetValue(anchor, out valuePromise)) { aliasState.Add(anchor, new ValuePromise(value)); } else if (!valuePromise.HasValue) { valuePromise.Value = value; } else { throw new DuplicateAnchorException(nodeEvent.Start, nodeEvent.End, string.Format( "Anchor '{0}' already defined", anchor )); } } return(value); }
/// <summary> /// Deserializes an object of the specified type. /// </summary> /// <param name="reader">The <see cref="EventReader" /> where to deserialize the object.</param> /// <param name="type">The static type of the object to deserialize.</param> /// <returns>Returns the deserialized object.</returns> public object Deserialize(EventReader reader, Type type, IValueDeserializer deserializer = null) { if (reader == null) { throw new ArgumentNullException("reader"); } if (type == null) { throw new ArgumentNullException("type"); } var hasStreamStart = reader.Allow <StreamStart>() != null; var hasDocumentStart = reader.Allow <DocumentStart>() != null; deserializer = deserializer ?? _valueDeserializer; object result = null; if (!reader.Accept <DocumentEnd>() && !reader.Accept <StreamEnd>()) { using (var state = new SerializerState()) { result = deserializer.DeserializeValue(reader, type, state, deserializer); state.OnDeserialization(); } } if (hasDocumentStart) { reader.Expect <DocumentEnd>(); } if (hasStreamStart) { reader.Expect <StreamEnd>(); } return(result); }
public bool Deserialize(EventReader reader, Type expectedType, Func<EventReader, Type, object> nestedObjectDeserializer, out object value) { if (reader == null) { value = null; return false; } // only try this if we're targeting a boolean or an untyped object if (expectedType == typeof(object) || expectedType == typeof(bool) ) { // peek at the current token Scalar scalar = reader.Peek<Scalar>(); // if it's unquoted if (scalar != null && scalar.Style == ScalarStyle.Plain) { // and the value is actually true or false switch (scalar.Value.ToUpperInvariant()) { case "TRUE": value = true; reader.Allow<Scalar>(); return true; case "FALSE": value = false; reader.Allow<Scalar>(); return true; } } } // otherwise, fall thru value = null; return false; }
public bool Deserialize(EventReader reader, Type expectedType, Func <EventReader, Type, object> nestedObjectDeserializer, out object value) { if (reader == null) { value = null; return(false); } // only try this if we're targeting a boolean or an untyped object if (expectedType == typeof(object) || expectedType == typeof(bool)) { // peek at the current token Scalar scalar = reader.Peek <Scalar>(); // if it's unquoted if (scalar != null && scalar.Style == ScalarStyle.Plain) { // and the value is actually true or false switch (scalar.Value.ToUpperInvariant()) { case "TRUE": value = true; reader.Allow <Scalar>(); return(true); case "FALSE": value = false; reader.Allow <Scalar>(); return(true); } } } // otherwise, fall thru value = null; return(false); }
public object DeserializeValue(EventReader reader, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer) { AnchorAlias alias = reader.Allow <AnchorAlias>(); if (alias != null) { ValuePromise promise; AliasState state2 = state.Get <AliasState>(); if (!state2.TryGetValue(alias.Value, out promise)) { promise = new ValuePromise(alias); state2.Add(alias.Value, promise); } return(!promise.HasValue ? promise : promise.Value); } string key = null; NodeEvent event2 = reader.Peek <NodeEvent>(); if ((event2 != null) && !string.IsNullOrEmpty(event2.Anchor)) { key = event2.Anchor; } object obj2 = this.innerDeserializer.DeserializeValue(reader, expectedType, state, nestedObjectDeserializer); if (key != null) { ValuePromise promise2; AliasState state3 = state.Get <AliasState>(); if (!state3.TryGetValue(key, out promise2)) { state3.Add(key, new ValuePromise(obj2)); } else { if (promise2.HasValue) { throw new DuplicateAnchorException(event2.Start, event2.End, $"Anchor '{key}' already defined"); } promise2.Value = obj2; } } return(obj2); }
bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func <EventReader, Type, object> nestedObjectDeserializer, out object value) { var mapping = reader.Allow <MappingStart>(); if (mapping == null) { value = null; return(false); } value = _objectFactory.Create(expectedType); while (!reader.Accept <MappingEnd>()) { var propertyName = reader.Expect <Scalar>(); var property = _typeDescriptor.GetProperty(expectedType, null, propertyName.Value, _ignoreUnmatched); if (property == null) { reader.SkipThisAndNestedEvents(); continue; } var propertyValue = nestedObjectDeserializer(reader, property.Type); var propertyValuePromise = propertyValue as IValuePromise; if (propertyValuePromise == null) { var convertedValue = TypeConverter.ChangeType(propertyValue, property.Type); property.Write(value, convertedValue); } else { var valueRef = value; propertyValuePromise.ValueAvailable += v => { var convertedValue = TypeConverter.ChangeType(v, property.Type); property.Write(valueRef, convertedValue); }; } } reader.Expect <MappingEnd>(); return(true); }
bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func<EventReader, Type, object> nestedObjectDeserializer, out object value) { var mapping = reader.Allow<MappingStart>(); if (mapping == null) { value = null; return false; } value = _objectFactory.Create(expectedType); while (!reader.Accept<MappingEnd>()) { var propertyName = reader.Expect<Scalar>(); var property = _typeDescriptor.GetProperty(expectedType, null, propertyName.Value, _ignoreUnmatched); if (property == null) { reader.SkipThisAndNestedEvents(); continue; } var propertyValue = nestedObjectDeserializer(reader, property.Type); var propertyValuePromise = propertyValue as IValuePromise; if (propertyValuePromise == null) { var convertedValue = TypeConverter.ChangeType(propertyValue, property.Type); property.Write(value, convertedValue); } else { var valueRef = value; propertyValuePromise.ValueAvailable += v => { var convertedValue = TypeConverter.ChangeType(v, property.Type); property.Write(valueRef, convertedValue); }; } } reader.Expect<MappingEnd>(); return true; }
public object DeserializeValue(EventReader reader, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer) { object value; var alias = reader.Allow <AnchorAlias>(); if (alias != null) { var aliasState = state.Get <AliasState>(); if (aliasState.TryGetValue(alias.Value, out value)) { return(value); } throw new AnchorNotFoundException(alias.Start, alias.End, string.Format( "Anchor '{0}' not found", alias.Value )); } string anchor = null; var nodeEvent = reader.Peek <NodeEvent>(); if (nodeEvent != null && !string.IsNullOrEmpty(nodeEvent.Anchor)) { anchor = nodeEvent.Anchor; } value = innerDeserializer.DeserializeValue(reader, expectedType, state, nestedObjectDeserializer); if (anchor != null) { var aliasState = state.Get <AliasState>(); aliasState.Add(anchor, value); } return(value); }
bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func <EventReader, Type, object> nestedObjectDeserializer, out object value) { var mapping = reader.Allow <MappingStart>(); if (mapping == null) { value = null; return(false); } value = _objectFactory.Create(expectedType); while (!reader.Accept <MappingEnd>()) { var propertyName = reader.Expect <Scalar>(); var property = _typeDescriptor.GetProperty(expectedType, propertyName.Value).Property; var propertyValue = nestedObjectDeserializer(reader, property.PropertyType); var convertedValue = TypeConverter.ChangeType(propertyValue, property.PropertyType); property.SetValue(value, convertedValue, null); } reader.Expect <MappingEnd>(); return(true); }
bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func <EventReader, Type, object> nestedObjectDeserializer, out object value) { Scalar scalar = reader.Allow <Scalar>(); if (scalar == null) { value = null; return(false); } if (expectedType.IsEnum()) { value = Enum.Parse(expectedType, scalar.Value, true); } else { TypeCode typeCode = expectedType.GetTypeCode(); switch (typeCode) { case TypeCode.Boolean: value = bool.Parse(scalar.Value); break; case TypeCode.Char: value = scalar.Value[0]; break; case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: value = this.DeserializeIntegerHelper(typeCode, scalar.Value, YamlFormatter.NumberFormat); break; case TypeCode.Single: value = float.Parse(scalar.Value, YamlFormatter.NumberFormat); break; case TypeCode.Double: value = double.Parse(scalar.Value, YamlFormatter.NumberFormat); break; case TypeCode.Decimal: value = decimal.Parse(scalar.Value, YamlFormatter.NumberFormat); break; case TypeCode.DateTime: value = DateTime.Parse(scalar.Value, CultureInfo.InvariantCulture); break; case TypeCode.String: value = scalar.Value; break; default: value = !ReferenceEquals(expectedType, typeof(object)) ? TypeConverter.ChangeType(scalar.Value, expectedType) : scalar.Value; break; } } return(true); }
public static bool MigrateAssetIfNeeded(AssetMigrationContext context, PackageLoadingAssetFile loadAsset, string dependencyName, PackageVersion untilVersion = null) { var assetFullPath = loadAsset.FilePath.FullPath; // Determine if asset was Yaml or not var assetFileExtension = Path.GetExtension(assetFullPath); if (assetFileExtension == null) { return(false); } assetFileExtension = assetFileExtension.ToLowerInvariant(); var serializer = AssetFileSerializer.FindSerializer(assetFileExtension); if (!(serializer is YamlAssetSerializer)) { return(false); } // We've got a Yaml asset, let's get expected and serialized versions var serializedVersion = PackageVersion.Zero; PackageVersion expectedVersion; Type assetType; // Read from Yaml file the asset version and its type (to get expected version) // Note: It tries to read as few as possible (SerializedVersion is expected to be right after Id, so it shouldn't try to read further than that) using (var assetStream = loadAsset.OpenStream()) using (var streamReader = new StreamReader(assetStream)) { var yamlEventReader = new EventReader(new Parser(streamReader)); // Skip header yamlEventReader.Expect <StreamStart>(); yamlEventReader.Expect <DocumentStart>(); var mappingStart = yamlEventReader.Expect <MappingStart>(); var tagTypeRegistry = AssetYamlSerializer.Default.GetSerializerSettings().TagTypeRegistry; bool typeAliased; assetType = tagTypeRegistry.TypeFromTag(mappingStart.Tag, out typeAliased); var expectedVersions = AssetRegistry.GetCurrentFormatVersions(assetType); expectedVersion = expectedVersions?.FirstOrDefault(x => x.Key == dependencyName).Value ?? PackageVersion.Zero; Scalar assetKey; while ((assetKey = yamlEventReader.Allow <Scalar>()) != null) { // Only allow Id before SerializedVersion if (assetKey.Value == nameof(Asset.Id)) { yamlEventReader.Skip(); } else if (assetKey.Value == nameof(Asset.SerializedVersion)) { // Check for old format: only a scalar var scalarVersion = yamlEventReader.Allow <Scalar>(); if (scalarVersion != null) { serializedVersion = PackageVersion.Parse("0.0." + Convert.ToInt32(scalarVersion.Value, CultureInfo.InvariantCulture)); // Let's update to new format using (var yamlAsset = loadAsset.AsYamlAsset()) { yamlAsset.DynamicRootNode.RemoveChild(nameof(Asset.SerializedVersion)); AssetUpgraderBase.SetSerializableVersion(yamlAsset.DynamicRootNode, dependencyName, serializedVersion); var baseBranch = yamlAsset.DynamicRootNode["~Base"]; if (baseBranch != null) { var baseAsset = baseBranch["Asset"]; if (baseAsset != null) { baseAsset.RemoveChild(nameof(Asset.SerializedVersion)); AssetUpgraderBase.SetSerializableVersion(baseAsset, dependencyName, serializedVersion); } } } } else { // New format: package => version mapping yamlEventReader.Expect <MappingStart>(); while (!yamlEventReader.Accept <MappingEnd>()) { var packageName = yamlEventReader.Expect <Scalar>().Value; var packageVersion = PackageVersion.Parse(yamlEventReader.Expect <Scalar>().Value); // For now, we handle only one dependency at a time if (packageName == dependencyName) { serializedVersion = packageVersion; } } yamlEventReader.Expect <MappingEnd>(); } break; } else { // If anything else than Id or SerializedVersion, let's stop break; } } } if (serializedVersion > expectedVersion) { // Try to open an asset newer than what we support (probably generated by a newer Stride) throw new InvalidOperationException($"Asset of type {assetType} has been serialized with newer version {serializedVersion}, but only version {expectedVersion} is supported. Was this asset created with a newer version of Stride?"); } if (serializedVersion < expectedVersion) { // Perform asset upgrade context.Log.Verbose($"{Path.GetFullPath(assetFullPath)} needs update, from version {serializedVersion} to version {expectedVersion}"); using (var yamlAsset = loadAsset.AsYamlAsset()) { var yamlRootNode = yamlAsset.RootNode; // Check if there is any asset updater var assetUpgraders = AssetRegistry.GetAssetUpgraders(assetType, dependencyName); if (assetUpgraders == null) { throw new InvalidOperationException($"Asset of type {assetType} should be updated from version {serializedVersion} to {expectedVersion}, but no asset migration path was found"); } // Instantiate asset updaters var currentVersion = serializedVersion; while (currentVersion != expectedVersion) { PackageVersion targetVersion; // This will throw an exception if no upgrader is available for the given version, exiting the loop in case of error. var upgrader = assetUpgraders.GetUpgrader(currentVersion, out targetVersion); // Stop if the next version would be higher than what is expected if (untilVersion != null && targetVersion > untilVersion) { break; } upgrader.Upgrade(context, dependencyName, currentVersion, targetVersion, yamlRootNode, loadAsset); currentVersion = targetVersion; } // Make sure asset is updated to latest version YamlNode serializedVersionNode; PackageVersion newSerializedVersion = null; if (yamlRootNode.Children.TryGetValue(new YamlScalarNode(nameof(Asset.SerializedVersion)), out serializedVersionNode)) { var newSerializedVersionForDefaultPackage = ((YamlMappingNode)serializedVersionNode).Children[new YamlScalarNode(dependencyName)]; newSerializedVersion = PackageVersion.Parse(((YamlScalarNode)newSerializedVersionForDefaultPackage).Value); } if (untilVersion == null && newSerializedVersion != expectedVersion) { throw new InvalidOperationException($"Asset of type {assetType} was migrated, but still its new version {newSerializedVersion} doesn't match expected version {expectedVersion}."); } context.Log.Verbose($"{Path.GetFullPath(assetFullPath)} updated from version {serializedVersion} to version {expectedVersion}"); } return(true); } return(false); }
bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func <EventReader, Type, object> nestedObjectDeserializer, out object value) { var scalar = reader.Allow <Scalar>(); if (scalar == null) { value = null; return(false); } if (expectedType.IsEnum) { value = Enum.Parse(expectedType, scalar.Value); } else { TypeCode typeCode = Type.GetTypeCode(expectedType); switch (typeCode) { case TypeCode.Boolean: value = bool.Parse(scalar.Value); break; case TypeCode.Byte: value = Byte.Parse(scalar.Value, numberFormat); break; case TypeCode.Int16: value = Int16.Parse(scalar.Value, numberFormat); break; case TypeCode.Int32: value = Int32.Parse(scalar.Value, numberFormat); break; case TypeCode.Int64: value = Int64.Parse(scalar.Value, numberFormat); break; case TypeCode.SByte: value = SByte.Parse(scalar.Value, numberFormat); break; case TypeCode.UInt16: value = UInt16.Parse(scalar.Value, numberFormat); break; case TypeCode.UInt32: value = UInt32.Parse(scalar.Value, numberFormat); break; case TypeCode.UInt64: value = UInt64.Parse(scalar.Value, numberFormat); break; case TypeCode.Single: value = Single.Parse(scalar.Value, numberFormat); break; case TypeCode.Double: value = Double.Parse(scalar.Value, numberFormat); break; case TypeCode.Decimal: value = Decimal.Parse(scalar.Value, numberFormat); break; case TypeCode.String: value = scalar.Value; break; case TypeCode.Char: value = scalar.Value[0]; break; case TypeCode.DateTime: // TODO: This is probably incorrect. Use the correct regular expression. value = DateTime.Parse(scalar.Value, CultureInfo.InvariantCulture); break; default: if (expectedType == typeof(object)) { // Default to string value = scalar.Value; } else { value = TypeConverter.ChangeType(scalar.Value, expectedType); } break; } } return(true); }
public static bool MigrateAssetIfNeeded(AssetMigrationContext context, PackageLoadingAssetFile loadAsset, string dependencyName, PackageVersion untilVersion = null) { var assetFullPath = loadAsset.FilePath.FullPath; // Determine if asset was Yaml or not var assetFileExtension = Path.GetExtension(assetFullPath); if (assetFileExtension == null) return false; assetFileExtension = assetFileExtension.ToLowerInvariant(); var serializer = AssetFileSerializer.FindSerializer(assetFileExtension); if (!(serializer is YamlAssetSerializer)) return false; // We've got a Yaml asset, let's get expected and serialized versions var serializedVersion = PackageVersion.Zero; PackageVersion expectedVersion; Type assetType; // Read from Yaml file the asset version and its type (to get expected version) // Note: It tries to read as few as possible (SerializedVersion is expected to be right after Id, so it shouldn't try to read further than that) using (var assetStream = loadAsset.OpenStream()) using (var streamReader = new StreamReader(assetStream)) { var yamlEventReader = new EventReader(new Parser(streamReader)); // Skip header yamlEventReader.Expect<StreamStart>(); yamlEventReader.Expect<DocumentStart>(); var mappingStart = yamlEventReader.Expect<MappingStart>(); var tagTypeRegistry = AssetYamlSerializer.Default.GetSerializerSettings().TagTypeRegistry; bool typeAliased; assetType = tagTypeRegistry.TypeFromTag(mappingStart.Tag, out typeAliased); var expectedVersions = AssetRegistry.GetCurrentFormatVersions(assetType); expectedVersion = expectedVersions?.FirstOrDefault(x => x.Key == dependencyName).Value ?? PackageVersion.Zero; Scalar assetKey; while ((assetKey = yamlEventReader.Allow<Scalar>()) != null) { // Only allow Id before SerializedVersion if (assetKey.Value == nameof(Asset.Id)) { yamlEventReader.Skip(); } else if (assetKey.Value == nameof(Asset.SerializedVersion)) { // Check for old format: only a scalar var scalarVersion = yamlEventReader.Allow<Scalar>(); if (scalarVersion != null) { serializedVersion = PackageVersion.Parse("0.0." + Convert.ToInt32(scalarVersion.Value, CultureInfo.InvariantCulture)); // Let's update to new format using (var yamlAsset = loadAsset.AsYamlAsset()) { yamlAsset.DynamicRootNode.RemoveChild(nameof(Asset.SerializedVersion)); AssetUpgraderBase.SetSerializableVersion(yamlAsset.DynamicRootNode, dependencyName, serializedVersion); var baseBranch = yamlAsset.DynamicRootNode["~Base"]; if (baseBranch != null) { var baseAsset = baseBranch["Asset"]; if (baseAsset != null) { baseAsset.RemoveChild(nameof(Asset.SerializedVersion)); AssetUpgraderBase.SetSerializableVersion(baseAsset, dependencyName, serializedVersion); } } } } else { // New format: package => version mapping yamlEventReader.Expect<MappingStart>(); while (!yamlEventReader.Accept<MappingEnd>()) { var packageName = yamlEventReader.Expect<Scalar>().Value; var packageVersion = PackageVersion.Parse(yamlEventReader.Expect<Scalar>().Value); // For now, we handle only one dependency at a time if (packageName == dependencyName) { serializedVersion = packageVersion; } } yamlEventReader.Expect<MappingEnd>(); } break; } else { // If anything else than Id or SerializedVersion, let's stop break; } } } if (serializedVersion > expectedVersion) { // Try to open an asset newer than what we support (probably generated by a newer Xenko) throw new InvalidOperationException($"Asset of type {assetType} has been serialized with newer version {serializedVersion}, but only version {expectedVersion} is supported. Was this asset created with a newer version of Xenko?"); } if (serializedVersion < expectedVersion) { // Perform asset upgrade context.Log.Verbose("{0} needs update, from version {1} to version {2}", Path.GetFullPath(assetFullPath), serializedVersion, expectedVersion); using (var yamlAsset = loadAsset.AsYamlAsset()) { var yamlRootNode = yamlAsset.RootNode; // Check if there is any asset updater var assetUpgraders = AssetRegistry.GetAssetUpgraders(assetType, dependencyName); if (assetUpgraders == null) { throw new InvalidOperationException($"Asset of type {assetType} should be updated from version {serializedVersion} to {expectedVersion}, but no asset migration path was found"); } // Instantiate asset updaters var currentVersion = serializedVersion; while (currentVersion != expectedVersion) { PackageVersion targetVersion; // This will throw an exception if no upgrader is available for the given version, exiting the loop in case of error. var upgrader = assetUpgraders.GetUpgrader(currentVersion, out targetVersion); // Stop if the next version would be higher than what is expected if (untilVersion != null && targetVersion > untilVersion) break; upgrader.Upgrade(context, dependencyName, currentVersion, targetVersion, yamlRootNode, loadAsset); currentVersion = targetVersion; } // Make sure asset is updated to latest version YamlNode serializedVersionNode; PackageVersion newSerializedVersion = null; if (yamlRootNode.Children.TryGetValue(new YamlScalarNode(nameof(Asset.SerializedVersion)), out serializedVersionNode)) { var newSerializedVersionForDefaultPackage = ((YamlMappingNode)serializedVersionNode).Children[new YamlScalarNode(dependencyName)]; newSerializedVersion = PackageVersion.Parse(((YamlScalarNode)newSerializedVersionForDefaultPackage).Value); } if (untilVersion == null && newSerializedVersion != expectedVersion) { throw new InvalidOperationException($"Asset of type {assetType} was migrated, but still its new version {newSerializedVersion} doesn't match expected version {expectedVersion}."); } context.Log.Info("{0} updated from version {1} to version {2}", Path.GetFullPath(assetFullPath), serializedVersion, expectedVersion); } return true; } return false; }
public static bool MigrateAssetIfNeeded(AssetMigrationContext context, PackageLoadingAssetFile loadAsset) { var assetFullPath = loadAsset.FilePath.FullPath; // Determine if asset was Yaml or not var assetFileExtension = Path.GetExtension(assetFullPath); if (assetFileExtension == null) { return(false); } assetFileExtension = assetFileExtension.ToLowerInvariant(); var serializer = AssetSerializer.FindSerializer(assetFileExtension); if (!(serializer is AssetYamlSerializer)) { return(false); } // We've got a Yaml asset, let's get expected and serialized versions var serializedVersion = 0; int expectedVersion; Type assetType; // Read from Yaml file the asset version and its type (to get expected version) // Note: It tries to read as few as possible (SerializedVersion is expected to be right after Id, so it shouldn't try to read further than that) using (var assetStream = loadAsset.OpenStream()) using (var streamReader = new StreamReader(assetStream)) { var yamlEventReader = new EventReader(new Parser(streamReader)); // Skip header yamlEventReader.Expect <StreamStart>(); yamlEventReader.Expect <DocumentStart>(); var mappingStart = yamlEventReader.Expect <MappingStart>(); var yamlSerializerSettings = YamlSerializer.GetSerializerSettings(); var tagTypeRegistry = yamlSerializerSettings.TagTypeRegistry; bool typeAliased; assetType = tagTypeRegistry.TypeFromTag(mappingStart.Tag, out typeAliased); expectedVersion = AssetRegistry.GetCurrentFormatVersion(assetType); Scalar assetKey; while ((assetKey = yamlEventReader.Allow <Scalar>()) != null) { // Only allow Id before SerializedVersion if (assetKey.Value == "Id") { yamlEventReader.Skip(); continue; } if (assetKey.Value == "SerializedVersion") { serializedVersion = Convert.ToInt32(yamlEventReader.Expect <Scalar>().Value, CultureInfo.InvariantCulture); break; } } } if (serializedVersion > expectedVersion) { // Try to open an asset newer than what we support (probably generated by a newer Paradox) throw new InvalidOperationException(string.Format("Asset of type {0} has been serialized with newer version {1}, but only version {2} is supported. Was this asset created with a newer version of Paradox?", assetType, serializedVersion, expectedVersion)); } if (serializedVersion < expectedVersion) { // Perform asset upgrade context.Log.Verbose("{0} needs update, from version {1} to version {2}", Path.GetFullPath(assetFullPath), serializedVersion, expectedVersion); // transform the stream into string. string assetAsString; using (var assetStream = loadAsset.OpenStream()) using (var assetStreamReader = new StreamReader(assetStream, Encoding.UTF8)) { assetAsString = assetStreamReader.ReadToEnd(); } // Load the asset as a YamlNode object var input = new StringReader(assetAsString); var yamlStream = new YamlStream(); yamlStream.Load(input); var yamlRootNode = (YamlMappingNode)yamlStream.Documents[0].RootNode; // Check if there is any asset updater var assetUpgraders = AssetRegistry.GetAssetUpgraders(assetType); if (assetUpgraders == null) { throw new InvalidOperationException(string.Format("Asset of type {0} should be updated from version {1} to {2}, but no asset migration path was found", assetType, serializedVersion, expectedVersion)); } // Instantiate asset updaters var currentVersion = serializedVersion; while (currentVersion != expectedVersion) { int targetVersion; // This will throw an exception if no upgrader is available for the given version, exiting the loop in case of error. var upgrader = assetUpgraders.GetUpgrader(currentVersion, out targetVersion); upgrader.Upgrade(context, currentVersion, targetVersion, yamlRootNode, loadAsset); currentVersion = targetVersion; } // Make sure asset is updated to latest version YamlNode serializedVersionNode; var newSerializedVersion = 0; if (yamlRootNode.Children.TryGetValue(new YamlScalarNode("SerializedVersion"), out serializedVersionNode)) { newSerializedVersion = Convert.ToInt32(((YamlScalarNode)serializedVersionNode).Value); } if (newSerializedVersion != expectedVersion) { throw new InvalidOperationException(string.Format("Asset of type {0} was migrated, but still its new version {1} doesn't match expected version {2}.", assetType, newSerializedVersion, expectedVersion)); } context.Log.Info("{0} updated from version {1} to version {2}", Path.GetFullPath(assetFullPath), serializedVersion, expectedVersion); var preferredIndent = YamlSerializer.GetSerializerSettings().PreferredIndent; // Save asset back to disk using (var memoryStream = new MemoryStream()) { using (var streamWriter = new StreamWriter(memoryStream)) { yamlStream.Save(streamWriter, true, preferredIndent); } loadAsset.AssetContent = memoryStream.ToArray(); } return(true); } return(false); }
public static bool MigrateAssetIfNeeded(ILogger log, string assetFullPath) { // Determine if asset was Yaml or not var assetFileExtension = Path.GetExtension(assetFullPath); if (assetFileExtension == null) { return(false); } assetFileExtension = assetFileExtension.ToLowerInvariant(); var serializer = AssetSerializer.FindSerializer(assetFileExtension); if (!(serializer is AssetYamlSerializer)) { return(false); } // We've got a Yaml asset, let's get expected and serialized versions var serializedVersion = 0; var expectedVersion = 0; Type assetType; // Read from Yaml file the asset version and its type (to get expected version) // Note: It tries to read as few as possible (SerializedVersion is expected to be right after Id, so it shouldn't try to read further than that) using (var streamReader = new StreamReader(assetFullPath)) { var yamlEventReader = new EventReader(new Parser(streamReader)); // Skip header yamlEventReader.Expect <StreamStart>(); yamlEventReader.Expect <DocumentStart>(); var mappingStart = yamlEventReader.Expect <MappingStart>(); var yamlSerializerSettings = YamlSerializer.GetSerializerSettings(); var tagTypeRegistry = yamlSerializerSettings.TagTypeRegistry; assetType = tagTypeRegistry.TypeFromTag(mappingStart.Tag); expectedVersion = AssetRegistry.GetFormatVersion(assetType); Scalar assetKey; while ((assetKey = yamlEventReader.Allow <Scalar>()) != null) { // Only allow Id before SerializedVersion if (assetKey.Value == "Id") { yamlEventReader.Skip(); continue; } if (assetKey.Value == "SerializedVersion") { serializedVersion = Convert.ToInt32(yamlEventReader.Expect <Scalar>().Value, CultureInfo.InvariantCulture); break; } } } if (serializedVersion > expectedVersion) { // Try to open an asset newer than what we support (probably generated by a newer Paradox) throw new InvalidOperationException(string.Format("Asset of type {0} has been serialized with newer version {1}, but only version {2} is supported. Was this asset created with a newer version of Paradox?", assetType, serializedVersion, expectedVersion)); } if (serializedVersion < expectedVersion) { // Perform asset upgrade log.Info("{0} needs update, from version {0} to version {1}", Path.GetFullPath(assetFullPath), serializedVersion, expectedVersion); // Load the asset as a YamlNode object var input = new StringReader(File.ReadAllText(assetFullPath)); var yamlStream = new YamlStream(); yamlStream.Load(input); var yamlRootNode = (YamlMappingNode)yamlStream.Documents[0].RootNode; // Check if there is any asset updater var assetUpdaterTypes = AssetRegistry.GetFormatVersionUpdaterTypes(assetType); if (assetUpdaterTypes == null) { throw new InvalidOperationException(string.Format("Asset of type {0} should be updated from version {1} to {2}, but no asset migration path was found", assetType, serializedVersion, expectedVersion)); } // Instantiate asset updaters var assetUpgraders = assetUpdaterTypes.Select(x => (IAssetUpgrader)Activator.CreateInstance(x)).ToArray(); // TODO: Select best asset updater if more than one (need to check from what to what version they update, score, if multiple need to be chained, etc...) // I think it's better to wait for some actual scenarios to implement this right the first time if (assetUpgraders.Length != 1) { throw new InvalidOperationException(string.Format("Asset of type {0} has multiple migration paths, but selecting the right one is not implemented yet.", assetType)); } // Perform upgrade assetUpgraders[0].Upgrade(log, yamlRootNode); // Make sure asset is updated to latest version YamlNode serializedVersionNode; serializedVersion = 0; if (yamlRootNode.Children.TryGetValue(new YamlScalarNode("SerializedVersion"), out serializedVersionNode)) { serializedVersion = Convert.ToInt32(((YamlScalarNode)serializedVersionNode).Value); } if (serializedVersion != expectedVersion) { throw new InvalidOperationException(string.Format("Asset of type {0} was migrated, but still its new version {1} doesn't match expected version {2}.", assetType, serializedVersion, expectedVersion)); } var preferredIndent = YamlSerializer.GetSerializerSettings().PreferredIndent; // Save asset back to disk using (var streamWriter = new StreamWriter(assetFullPath)) yamlStream.Save(streamWriter, true, preferredIndent); return(true); } return(false); }
bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func<EventReader, Type, object> nestedObjectDeserializer, out object value) { var scalar = reader.Allow<Scalar>(); if (scalar == null) { value = null; return false; } if (expectedType.IsEnum()) { value = Enum.Parse(expectedType, scalar.Value); } else { TypeCode typeCode = expectedType.GetTypeCode(); switch (typeCode) { case TypeCode.Boolean: value = bool.Parse(scalar.Value); break; case TypeCode.Byte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.SByte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: value = DeserializeIntegerHelper(typeCode, scalar.Value, YamlFormatter.NumberFormat); break; case TypeCode.Single: value = Single.Parse(scalar.Value, YamlFormatter.NumberFormat); break; case TypeCode.Double: value = Double.Parse(scalar.Value, YamlFormatter.NumberFormat); break; case TypeCode.Decimal: value = Decimal.Parse(scalar.Value, YamlFormatter.NumberFormat); break; case TypeCode.String: value = scalar.Value; break; case TypeCode.Char: value = scalar.Value[0]; break; case TypeCode.DateTime: // TODO: This is probably incorrect. Use the correct regular expression. value = DateTime.Parse(scalar.Value, CultureInfo.InvariantCulture); break; default: if (expectedType == typeof(object)) { // Default to string value = scalar.Value; } else { value = TypeConverter.ChangeType(scalar.Value, expectedType); } break; } } return true; }
public static bool MigrateAssetIfNeeded(AssetMigrationContext context, PackageLoadingAssetFile loadAsset) { var assetFullPath = loadAsset.FilePath.FullPath; // Determine if asset was Yaml or not var assetFileExtension = Path.GetExtension(assetFullPath); if (assetFileExtension == null) return false; assetFileExtension = assetFileExtension.ToLowerInvariant(); var serializer = AssetSerializer.FindSerializer(assetFileExtension); if (!(serializer is AssetYamlSerializer)) return false; // We've got a Yaml asset, let's get expected and serialized versions var serializedVersion = 0; int expectedVersion; Type assetType; // Read from Yaml file the asset version and its type (to get expected version) // Note: It tries to read as few as possible (SerializedVersion is expected to be right after Id, so it shouldn't try to read further than that) using (var assetStream = loadAsset.OpenStream()) using (var streamReader = new StreamReader(assetStream)) { var yamlEventReader = new EventReader(new Parser(streamReader)); // Skip header yamlEventReader.Expect<StreamStart>(); yamlEventReader.Expect<DocumentStart>(); var mappingStart = yamlEventReader.Expect<MappingStart>(); var yamlSerializerSettings = YamlSerializer.GetSerializerSettings(); var tagTypeRegistry = yamlSerializerSettings.TagTypeRegistry; bool typeAliased; assetType = tagTypeRegistry.TypeFromTag(mappingStart.Tag, out typeAliased); expectedVersion = AssetRegistry.GetCurrentFormatVersion(assetType); Scalar assetKey; while ((assetKey = yamlEventReader.Allow<Scalar>()) != null) { // Only allow Id before SerializedVersion if (assetKey.Value == "Id") { yamlEventReader.Skip(); continue; } if (assetKey.Value == "SerializedVersion") { serializedVersion = Convert.ToInt32(yamlEventReader.Expect<Scalar>().Value, CultureInfo.InvariantCulture); break; } } } if (serializedVersion > expectedVersion) { // Try to open an asset newer than what we support (probably generated by a newer Paradox) throw new InvalidOperationException(string.Format("Asset of type {0} has been serialized with newer version {1}, but only version {2} is supported. Was this asset created with a newer version of Paradox?", assetType, serializedVersion, expectedVersion)); } if (serializedVersion < expectedVersion) { // Perform asset upgrade context.Log.Verbose("{0} needs update, from version {1} to version {2}", Path.GetFullPath(assetFullPath), serializedVersion, expectedVersion); // transform the stream into string. string assetAsString; using (var assetStream = loadAsset.OpenStream()) using (var assetStreamReader = new StreamReader(assetStream, Encoding.UTF8)) { assetAsString = assetStreamReader.ReadToEnd(); } // Load the asset as a YamlNode object var input = new StringReader(assetAsString); var yamlStream = new YamlStream(); yamlStream.Load(input); var yamlRootNode = (YamlMappingNode)yamlStream.Documents[0].RootNode; // Check if there is any asset updater var assetUpgraders = AssetRegistry.GetAssetUpgraders(assetType); if (assetUpgraders == null) { throw new InvalidOperationException(string.Format("Asset of type {0} should be updated from version {1} to {2}, but no asset migration path was found", assetType, serializedVersion, expectedVersion)); } // Instantiate asset updaters var currentVersion = serializedVersion; while (currentVersion != expectedVersion) { int targetVersion; // This will throw an exception if no upgrader is available for the given version, exiting the loop in case of error. var upgrader = assetUpgraders.GetUpgrader(currentVersion, out targetVersion); upgrader.Upgrade(context, currentVersion, targetVersion, yamlRootNode, loadAsset); currentVersion = targetVersion; } // Make sure asset is updated to latest version YamlNode serializedVersionNode; var newSerializedVersion = 0; if (yamlRootNode.Children.TryGetValue(new YamlScalarNode("SerializedVersion"), out serializedVersionNode)) { newSerializedVersion = Convert.ToInt32(((YamlScalarNode)serializedVersionNode).Value); } if (newSerializedVersion != expectedVersion) { throw new InvalidOperationException(string.Format("Asset of type {0} was migrated, but still its new version {1} doesn't match expected version {2}.", assetType, newSerializedVersion, expectedVersion)); } context.Log.Info("{0} updated from version {1} to version {2}", Path.GetFullPath(assetFullPath), serializedVersion, expectedVersion); var preferredIndent = YamlSerializer.GetSerializerSettings().PreferredIndent; // Save asset back to disk using (var memoryStream = new MemoryStream()) { using (var streamWriter = new StreamWriter(memoryStream)) { yamlStream.Save(streamWriter, true, preferredIndent); } loadAsset.AssetContent = memoryStream.ToArray(); } return true; } return false; }
/// <summary> /// Deserializes an object of the specified type. /// </summary> /// <param name="reader">The <see cref="EventReader" /> where to deserialize the object.</param> /// <param name="type">The static type of the object to deserialize.</param> /// <param name="options">Options that control how the deserialization is to be performed.</param> /// <returns>Returns the deserialized object.</returns> public object Deserialize(EventReader reader, Type type, DeserializationOptions options = DeserializationOptions.None) { if (reader == null) { throw new ArgumentNullException("reader"); } if (type == null) { throw new ArgumentNullException("type"); } var hasStreamStart = reader.Allow<StreamStart>() != null; var hasDocumentStart = reader.Allow<DocumentStart>() != null; if (hasDocumentStart) { reader.Expect<DocumentEnd>(); } if (hasStreamStart) { reader.Expect<StreamEnd>(); } }
public static YamlValue Load(EventReader eventReader, YamlNodeTracker tracker = null) { var scalar = eventReader.Allow <Scalar>(); return(new YamlValue(scalar, tracker)); }