public void TestBuilderAdd()
        {
            var builder1 = new BinaryCodeBuilder(
                new byte[] { 100, 255 }
                );
            var builder2 = new BinaryCodeBuilder();

            var bytes = new byte[] { 100, 255, 201 };

            builder1.AppendBit(1);
            builder1.AppendBit(0);
            builder1.AppendBit(0);
            builder1.AppendBit(1);
            builder1.AppendBit(0);

            builder2.Append(builder1);
            builder2.AppendBit(0);
            builder2.AppendBit(1);
            builder2.AppendBit(1);

            var storedBytes2 = builder2.ToBytes();

            for (int i = 0; i < bytes.Length; i++)
            {
                Assert.AreEqual(bytes[i], storedBytes2[i]);
            }
        }
        protected virtual IEnumerable <byte> ComplexTypeEncoder(object o)
        {
            bool firstLevelEncoding = false;

            if (_encodedComplexObjects == null)
            {
                firstLevelEncoding     = true;
                _encodedComplexObjects = new List <object>();
            }

            if (_encodedComplexObjects.Contains(o))
            {
                // Infinite encoding loop detected
                throw new InfiniteEncodingLoopException(o, "Infinite encoding loop detected");
            }

            _encodedComplexObjects.Add(o);             // Remember we already encoded this one object in particular

            List <byte> result = new List <byte>();
            Type        t      = o.GetType();

            // Original type accessable fields (all fields apart from private fields in base types as these are not inherited)
            var hierarchyFieldInfos = new List <FieldInfo[]>();

            hierarchyFieldInfos.Add(t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic));
            Type inherited = t.BaseType;

            // Base types non-public fields (later restricted to private fields only)
            while (inherited != null && inherited != typeof(object))
            {
                hierarchyFieldInfos.Add(inherited.GetFields(BindingFlags.Instance | BindingFlags.NonPublic));

                inherited = inherited.BaseType;
            }

            int               hierarchyDescentCounter = 0;    // How many times to go up the class parent hierarchy to get access to currently encoded private fields
            bool              originalType            = true; // whether we are currently encoding fields accessable from the object type, not parent types
            object            currentlyEncodedObject;
            BinaryCodeBuilder encodedAsBuilder;
            BinaryCodeBuilder builder = new BinaryCodeBuilder();

            foreach (var fieldArr in hierarchyFieldInfos)
            {
                foreach (var field in fieldArr)
                {
                    if (field.IsPrivate || originalType)
                    {
                        if (hierarchyDescentCounter > 0)
                        {
                            for (int i = 0; i < hierarchyDescentCounter; i++)
                            {
                                builder.AppendBit(1);
                            }
                            hierarchyDescentCounter = 0;
                        }
                        builder.AppendBit(0);                         // 0 indicates end of going up the class hierarchy

                        byte[] bytes = EncodeFieldName(field.Name);
                        builder.Append(EncodeLength((uint)bytes.Length));
                        builder.AppendBytes(bytes);

                        currentlyEncodedObject = field.GetValue(o);
                        encodedAsBuilder       = Encode(currentlyEncodedObject);
                        builder.Append(encodedAsBuilder);
                    }
                }

                hierarchyDescentCounter++;
                originalType = false;
            }

            if (firstLevelEncoding)
            {
                _encodedComplexObjects.Clear();
                _encodedComplexObjects = null;
            }

            return(builder);
        }