/// <summary> /// Skips the next entry value, unless it is an <see cref="EntryType.EndOfNode"/> or an <see cref="EntryType.EndOfArray"/>. If the next entry value is an <see cref="EntryType.StartOfNode"/> or an <see cref="EntryType.StartOfArray"/>, all of its contents will be processed, deserialized and registered in the deserialization context, so that internal reference values are not lost to entries further down the stream. /// </summary> public virtual void SkipEntry() { var peekedEntry = this.PeekEntry(); if (peekedEntry == EntryType.StartOfNode) { Type type; bool exitNode = true; this.EnterNode(out type); try { if (type != null) { // We have the necessary metadata to read this type, and register all of its reference values (perhaps including itself) in the serialization context // Sadly, we have no choice but to risk boxing of structs here // Luckily, this is a rare case if (FormatterUtilities.IsPrimitiveType(type)) { // It is a boxed primitive type; we read the value and register it var serializer = Serializer.Get(type); object value = serializer.ReadValueWeak(this); if (this.CurrentNodeId >= 0) { this.Context.RegisterInternalReference(this.CurrentNodeId, value); } } else { var formatter = FormatterLocator.GetFormatter(type, this.Context.Config.SerializationPolicy); object value = formatter.Deserialize(this); if (this.CurrentNodeId >= 0) { this.Context.RegisterInternalReference(this.CurrentNodeId, value); } } } else { // We have no metadata, and reference values might be lost // We must read until a node on the same level terminates while (true) { peekedEntry = this.PeekEntry(); if (peekedEntry == EntryType.EndOfStream) { break; } else if (peekedEntry == EntryType.EndOfNode) { break; } else if (peekedEntry == EntryType.EndOfArray) { this.ReadToNextEntry(); // Consume end of arrays that we can potentially get stuck on } else { this.SkipEntry(); } } } } catch (SerializationAbortException ex) { exitNode = false; throw ex; } finally { if (exitNode) { this.ExitNode(); } } } else if (peekedEntry == EntryType.StartOfArray) { // We must read until an array on the same level terminates this.ReadToNextEntry(); // Consume start of array while (true) { peekedEntry = this.PeekEntry(); if (peekedEntry == EntryType.EndOfStream) { break; } else if (peekedEntry == EntryType.EndOfArray) { this.ReadToNextEntry(); // Consume end of array and break break; } else if (peekedEntry == EntryType.EndOfNode) { this.ReadToNextEntry(); // Consume end of nodes that we can potentially get stuck on } else { this.SkipEntry(); } } } else if (peekedEntry != EntryType.EndOfArray && peekedEntry != EntryType.EndOfNode) // We can't skip end of arrays and end of nodes { this.ReadToNextEntry(); // We can just skip a single value entry } }