Esempio n. 1
0
        /// <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
            }
        }