Deserializer
General binary format deserializer.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Formats.Nrbf;
using System.Private.Windows.Core.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System.Private.Windows.BinaryFormat
{
[NullableContext(1)]
[Nullable(0)]
internal sealed class Deserializer : IDeserializer
{
private readonly IReadOnlyDictionary<SerializationRecordId, SerializationRecord> _recordMap;
private readonly ITypeResolver _typeResolver;
private readonly Dictionary<SerializationRecordId, object> _deserializedObjects = new Dictionary<SerializationRecordId, object>();
[Nullable(new byte[] {
2,
1,
2
})]
private readonly Dictionary<Type, ISerializationSurrogate> _surrogates;
[Nullable(new byte[] {
2,
1
})]
private Queue<PendingSerializationInfo> _pendingSerializationInfo;
[Nullable(2)]
private HashSet<SerializationRecordId> _pendingSerializationInfoIds;
private readonly Stack<ObjectRecordDeserializer> _parserStack = new Stack<ObjectRecordDeserializer>();
private readonly HashSet<SerializationRecordId> _incompleteObjects = new HashSet<SerializationRecordId>();
[Nullable(new byte[] {
2,
1
})]
private Dictionary<SerializationRecordId, HashSet<SerializationRecordId>> _incompleteDependencies;
[Nullable(new byte[] {
2,
1
})]
private HashSet<ValueUpdater> _pendingUpdates;
private readonly Queue<SerializationRecordId> _pendingCompletions = new Queue<SerializationRecordId>();
private readonly SerializationRecordId _rootId;
ITypeResolver IDeserializer.TypeResolver {
get {
return _typeResolver;
}
}
private DeserializationOptions Options { get; }
DeserializationOptions IDeserializer.Options {
get {
return Options;
}
}
IDictionary<SerializationRecordId, object> IDeserializer.DeserializedObjects {
get {
return _deserializedObjects;
}
}
public HashSet<SerializationRecordId> IncompleteObjects => _incompleteObjects;
[Nullable(2)]
[method: NullableContext(2)]
[field: Nullable(2)]
private event Action<object> OnDeserialization;
[Nullable(2)]
[method: NullableContext(2)]
[field: Nullable(2)]
private event Action<StreamingContext> OnDeserialized;
private Deserializer(SerializationRecordId rootId, IReadOnlyDictionary<SerializationRecordId, SerializationRecord> recordMap, DeserializationOptions options)
{
_rootId = rootId;
_recordMap = recordMap;
_typeResolver = (options.TypeResolver ?? new DefaultTypeResolver(options));
Options = options;
if (Options.SurrogateSelector != null)
_surrogates = new Dictionary<Type, ISerializationSurrogate>();
}
[RequiresUnreferencedCode("Calls System.Windows.Forms.BinaryFormat.Deserializer.Deserializer.Deserialize()")]
internal static object Deserialize(SerializationRecordId rootId, IReadOnlyDictionary<SerializationRecordId, SerializationRecord> recordMap, DeserializationOptions options)
{
return new Deserializer(rootId, recordMap, options).Deserialize();
}
[RequiresUnreferencedCode("Calls System.Windows.Forms.BinaryFormat.Deserializer.Deserializer.DeserializeRoot(SerializationRecordId)")]
private object Deserialize()
{
DeserializeRoot(_rootId);
Queue<PendingSerializationInfo> pendingSerializationInfo = _pendingSerializationInfo;
int num = (pendingSerializationInfo != null) ? pendingSerializationInfo.Count : 0;
while (_pendingSerializationInfo != null && _pendingSerializationInfo.Count > 0) {
PendingSerializationInfo pendingSerializationInfo2 = _pendingSerializationInfo.Dequeue();
HashSet<SerializationRecordId> value;
if (--num >= 0 && _pendingSerializationInfo.Count != 0 && _incompleteDependencies != null && _incompleteDependencies.TryGetValue(pendingSerializationInfo2.ObjectId, out value) && value.Count > 0)
_pendingSerializationInfo.Enqueue(pendingSerializationInfo2);
else {
pendingSerializationInfo2.Populate(_deserializedObjects, Options.StreamingContext);
_pendingSerializationInfoIds?.Remove(pendingSerializationInfo2.ObjectId);
((IDeserializer)this).CompleteObject(pendingSerializationInfo2.ObjectId);
}
}
if (_incompleteObjects.Count > 0 || (_pendingUpdates != null && _pendingUpdates.Count > 0))
throw new SerializationException(System.Private.Windows.Core.Resources.SR.Serialization_Incomplete);
this.OnDeserialized?.Invoke(Options.StreamingContext);
this.OnDeserialization?.Invoke(null);
return _deserializedObjects[_rootId];
}
[RequiresUnreferencedCode("Calls DeserializeNew(SerializationRecordId)")]
private void DeserializeRoot(SerializationRecordId rootId)
{
ObjectRecordDeserializer objectRecordDeserializer = <DeserializeRoot>g__DeserializeNew|32_0(rootId) as ObjectRecordDeserializer;
if (objectRecordDeserializer != null) {
_parserStack.Push(objectRecordDeserializer);
while (_parserStack.Count > 0) {
ObjectRecordDeserializer objectRecordDeserializer2 = _parserStack.Pop();
while (true) {
SerializationRecordId id;
SerializationRecordId val = id = objectRecordDeserializer2.Continue();
if (val.Equals(default(SerializationRecordId)))
break;
ObjectRecordDeserializer objectRecordDeserializer3 = <DeserializeRoot>g__DeserializeNew|32_0(id) as ObjectRecordDeserializer;
if (objectRecordDeserializer3 != null) {
_parserStack.Push(objectRecordDeserializer2);
_parserStack.Push(objectRecordDeserializer3);
break;
}
}
}
}
}
[return: Nullable(2)]
ISerializationSurrogate IDeserializer.GetSurrogate(Type type)
{
if (_surrogates == null)
return null;
if (!_surrogates.TryGetValue(type, out ISerializationSurrogate value)) {
value = Options.SurrogateSelector.GetSurrogate(type, Options.StreamingContext, out ISurrogateSelector _);
_surrogates[type] = value;
}
return value;
}
void IDeserializer.PendSerializationInfo(PendingSerializationInfo pending)
{
if (_pendingSerializationInfo == null)
_pendingSerializationInfo = new Queue<PendingSerializationInfo>();
_pendingSerializationInfo.Enqueue(pending);
if (_pendingSerializationInfoIds == null)
_pendingSerializationInfoIds = new HashSet<SerializationRecordId>();
_pendingSerializationInfoIds.Add(pending.ObjectId);
}
void IDeserializer.PendValueUpdater(ValueUpdater updater)
{
if (_pendingUpdates == null)
_pendingUpdates = new HashSet<ValueUpdater>();
_pendingUpdates.Add(updater);
if (_incompleteDependencies == null)
_incompleteDependencies = new Dictionary<SerializationRecordId, HashSet<SerializationRecordId>>();
if (_incompleteDependencies.TryGetValue(updater.ObjectId, out HashSet<SerializationRecordId> value))
value.Add(updater.ValueId);
else
_incompleteDependencies.Add(updater.ObjectId, new HashSet<SerializationRecordId> {
updater.ValueId
});
}
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "The type is already in the cache of the TypeResolver, no need to mark this one again.")]
void IDeserializer.CompleteObject(SerializationRecordId id)
{
_pendingCompletions.Enqueue(id);
SerializationRecordId val = default(SerializationRecordId);
while (_pendingCompletions.Count > 0) {
SerializationRecordId completedId = _pendingCompletions.Dequeue();
_incompleteObjects.Remove(completedId);
if (!val.Equals(default(SerializationRecordId))) {
_incompleteDependencies?.Remove(val);
if (_pendingSerializationInfoIds != null && _pendingSerializationInfoIds.Contains(val))
continue;
val = default(SerializationRecordId);
}
ClassRecord val2 = _recordMap[completedId] as ClassRecord;
if (val2 != null && (_incompleteDependencies == null || !_incompleteDependencies.ContainsKey(completedId))) {
Type type = _typeResolver.BindToType(val2.get_TypeName());
object obj = _deserializedObjects[completedId];
OnDeserialized += SerializationEvents.GetOnDeserializedForType(type, obj);
IDeserializationCallback deserializationCallback = obj as IDeserializationCallback;
if (deserializationCallback != null) {
IDeserializationCallback deserializationCallback2 = deserializationCallback;
OnDeserialization += deserializationCallback2.OnDeserialization;
}
IObjectReference objectReference = obj as IObjectReference;
if (objectReference != null)
_deserializedObjects[completedId] = objectReference.GetRealObject(Options.StreamingContext);
}
if (_incompleteDependencies != null) {
foreach (KeyValuePair<SerializationRecordId, HashSet<SerializationRecordId>> incompleteDependency in _incompleteDependencies) {
SerializationRecordId key = incompleteDependency.Key;
HashSet<SerializationRecordId> value = incompleteDependency.Value;
if (value.Remove(completedId)) {
_pendingUpdates.RemoveWhere(delegate(ValueUpdater updater) {
SerializationRecordId valueId = updater.ValueId;
if (!valueId.Equals(completedId))
return false;
updater.UpdateValue(_deserializedObjects);
return true;
});
if (value.Count == 0) {
val = key;
_pendingCompletions.Enqueue(key);
}
}
}
}
}
}
}
}