// This file is part of YamlDotNet - A .NET library for YAML. // Copyright (c) Antoine Aubry and contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. using System; using System.IO; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Serialization.Utilities; namespace YamlDotNet.Serialization { /// /// Deserializes objects from the YAML format. /// To customize the behavior of , /// use the class. /// public sealed class Deserializer : IDeserializer { private readonly IValueDeserializer valueDeserializer; /// /// Initializes a new instance of using the default configuration. /// /// /// To customize the behavior of the deserializer, use . /// public Deserializer() : this(new DeserializerBuilder().BuildValueDeserializer()) { } /// /// This constructor is private to discourage its use. /// To invoke it, call the method. /// private Deserializer(IValueDeserializer valueDeserializer) { this.valueDeserializer = valueDeserializer ?? throw new ArgumentNullException(nameof(valueDeserializer)); } /// /// Creates a new that uses the specified . /// This method is available for advanced scenarios. The preferred way to customize the behavior of the /// deserializer is to use . /// public static Deserializer FromValueDeserializer(IValueDeserializer valueDeserializer) { return new Deserializer(valueDeserializer); } public T Deserialize(string input) { using var reader = new StringReader(input); return Deserialize(reader); } public T Deserialize(TextReader input) { return Deserialize(new Parser(input)); } public object? Deserialize(TextReader input) { return Deserialize(input, typeof(object)); } public object? Deserialize(string input, Type type) { using var reader = new StringReader(input); return Deserialize(reader, type); } public object? Deserialize(TextReader input, Type type) { return Deserialize(new Parser(input), type); } public T Deserialize(IParser parser) { return (T)Deserialize(parser, typeof(T))!; // We really want an exception if we are trying to deserialize null into a non-nullable type } public object? Deserialize(IParser parser) { return Deserialize(parser, typeof(object)); } /// /// Deserializes an object of the specified type. /// /// The from where to deserialize the object. /// The static type of the object to deserialize. /// Returns the deserialized object. public object? Deserialize(IParser parser, Type type) { if (parser == null) { throw new ArgumentNullException(nameof(parser)); } if (type == null) { throw new ArgumentNullException(nameof(type)); } var hasStreamStart = parser.TryConsume(out var _); var hasDocumentStart = parser.TryConsume(out var _); object? result = null; if (!parser.Accept(out var _) && !parser.Accept(out var _)) { using var state = new SerializerState(); result = valueDeserializer.DeserializeValue(parser, type, state, valueDeserializer); state.OnDeserialization(); } if (hasDocumentStart) { parser.Consume(); } if (hasStreamStart) { parser.Consume(); } return result; } } }