unsafe static int TrySerializer <T>(StringBuilder sb, params T[] samples)
        {
            int failures = 0;

            sb.AppendLine();
            sb.AppendLine("# " + SchemaTest.HumanName(typeof(T)));
            sb.AppendLine();

            var    emit = DelegateBuilder.CreateStream <T>(Schema.Reflect(typeof(T)));
            string instructions;
            var    del = (Serializer.WriteToStream <T>)emit.CreateDelegate(typeof(Serializer.WriteToStream <T>), out instructions);

            sb.AppendLine(emit.Instructions());
            sb.AppendLine();

            var ms     = new MemoryStream();
            var buffer = new byte[64];

            for (int i = 0; i < samples.Length; i++)
            {
                ms.Position = 0;
                fixed(byte *ptr = buffer)
                {
                    del.Invoke(ref samples[i], ptr, ms, buffer);
                }

                var newt = DelegateBuilderTest.GetNewtonsoft(samples[i]);
                var mine = ms.GetBuffer().Take((int)ms.Position);

                sb.AppendLine();
                sb.AppendLine("## Newtonsoft");
                Util.Hex.Dump(sb, newt);
                sb.AppendLine();

                sb.AppendLine();
                sb.AppendLine("## Cameronism.Json");
                Util.Hex.Dump(sb, mine);
                sb.AppendLine();
                sb.AppendLine();

                bool equal = newt.SequenceEqual(mine);
                sb.AppendLine("Equal: " + equal);
                sb.AppendLine();

                if (!equal)
                {
                    failures++;
                }
            }

            return(failures);
        }
        unsafe string ToJson <T>(T value, StreamSpy ss, out string instructions)
        {
            var ms = ss.Underlying as MemoryStream;

            ms.Position = 0;
            try
            {
                var schema = Schema.Reflect(typeof(T));
                var emit   = DelegateBuilder.CreateStream <T>(schema);
                var del    = emit.CreateDelegate <Serializer.WriteToStream <T> >(out instructions);
                fixed(byte *ptr = _Buffer)
                {
                    del.Invoke(ref value, ptr, ss, _Buffer);
                }
            }
            catch (Sigil.SigilVerificationException sve)
            {
                Trace.WriteLine(sve);
                instructions = sve.GetDebugInfo();
                throw;
            }
            return(Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Position));
        }
        public void BadUsage()
        {
            var badSchema = new Schema {
                JsonType = (JsonType)int.MaxValue
            };

            Assert.Throws <ArgumentException>(() => DelegateBuilder.CreateStream <int>(badSchema));

            badSchema = new Schema {
                JsonType = JsonType.Boolean, NetType = this.GetType()
            };
            Assert.Throws <ArgumentException>(() => DelegateBuilder.CreateStream <int>(badSchema));

            badSchema = new Schema
            {
                JsonType = JsonType.Array,
                NetType  = typeof(int[]),
                Items    = new Schema
                {
                    JsonType = (JsonType)int.MaxValue,
                    NetType  = typeof(int),
                }
            };
            Assert.Throws <ArgumentException>(() => DelegateBuilder.CreateStream <int[]>(badSchema));

            badSchema = new Schema
            {
                JsonType = JsonType.Array,
                NetType  = typeof(int[]),
                Items    = new Schema
                {
                    JsonType = JsonType.Integer,
                    NetType  = this.GetType(),
                }
            };
            Assert.Throws <ArgumentException>(() => DelegateBuilder.CreateStream <int[]>(badSchema));
        }
        // returns the length of serialized value when successful
        unsafe static int?CheckBoundary <T>(T value, int maxLength = 64)
        {
            const byte init   = 255;
            var        nJSON  = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(value));
            var        buffer = new byte[maxLength + 2];
            var        emit   = DelegateBuilder.CreatePointer <T>(Schema.Reflect(typeof(T)));
            string     instructions;
            var        del           = (Serializer.WriteToPointer <T>)emit.CreateDelegate(typeof(Serializer.WriteToPointer <T>), out instructions);
            int?       successLength = null;

            for (int i = 1; i <= maxLength; i++)
            {
                for (int j = 0; j < buffer.Length; j++)
                {
                    buffer[j] = init;
                }

                int result;
                fixed(byte *ptr = buffer)
                {
                    result = del.Invoke(ref value, ptr + 1, i);
                }

                // make sure we didn't go past the boundary
                Assert.Equal(init, buffer[0]);
                Assert.Equal(init, buffer[i + 1]);
                Assert.True(result <= i, "Don't exceed length");

                if (result > 0)
                {
                    Assert.Equal(nJSON, buffer.Skip(1).Take(result));
                    if (successLength == null)
                    {
                        successLength = i;
                    }
                }
            }

            if (successLength.HasValue)
            {
                emit = DelegateBuilder.CreateStream <T>(Schema.Reflect(typeof(T)));
                var streamer = (Serializer.WriteToStream <T>)emit.CreateDelegate(typeof(Serializer.WriteToStream <T>), out instructions);
                var min      = Math.Max(nJSON.Length / 2, 32);
                var ms       = new MemoryStream(nJSON.Length);

                // do stuff with the stream version now
                for (int i = nJSON.Length; i >= min; i--)
                {
                    ms.SetLength(0);
                    buffer = new byte[i];
                    fixed(byte *ptr = buffer)
                    {
                        streamer.Invoke(ref value, ptr, ms, buffer);
                    }

                    Assert.Equal(nJSON, ms.GetBuffer().Take((int)ms.Length));
                }
            }

            return(successLength);
        }