/// <summary>
        /// return buffer is from memory pool, be careful to use.
        /// </summary>
        internal static ArraySegment <byte> FromJsonUnsafe(TextReader reader)
        {
            var offset = 0;

            byte[] binary = InternalMemoryPool.GetBuffer();  // from memory pool.
            using (var jr = new TinyJsonReader(reader, false))
            {
                FromJsonCore(jr, ref binary, ref offset);
            }
            return(new ArraySegment <byte>(binary, 0, offset));
        }
        /// <summary>
        /// From Json String to Jetsons.MsgPack binary
        /// </summary>
        public static byte[] FromJson(TextReader reader)
        {
            var offset = 0;

            byte[] binary = null;
            using (var jr = new TinyJsonReader(reader, false))
            {
                FromJsonCore(jr, ref binary, ref offset);
            }
            MessagePackBinary.FastResize(ref binary, offset);
            return(binary);
        }
        static uint FromJsonCore(TinyJsonReader jr, ref byte[] binary, ref int offset)
        {
            uint count = 0;

            while (jr.Read())
            {
                switch (jr.TokenType)
                {
                case TinyJsonToken.None:
                    break;

                case TinyJsonToken.StartObject:
                {
                    var startOffset = offset;
                    offset += 5;
                    var mapCount = FromJsonCore(jr, ref binary, ref offset);
                    mapCount = mapCount / 2;         // remove propertyname string count.
                    MessagePackBinary.WriteMapHeaderForceMap32Block(ref binary, startOffset, mapCount);
                    count++;
                    break;
                }

                case TinyJsonToken.EndObject:
                    return(count);    // break

                case TinyJsonToken.StartArray:
                {
                    var startOffset = offset;
                    offset += 5;
                    var arrayCount = FromJsonCore(jr, ref binary, ref offset);
                    MessagePackBinary.WriteArrayHeaderForceArray32Block(ref binary, startOffset, arrayCount);
                    count++;
                    break;
                }

                case TinyJsonToken.EndArray:
                    return(count);    // break

                case TinyJsonToken.Number:
                    var v = jr.ValueType;
                    if (v == ValueType.Double)
                    {
                        offset += MessagePackBinary.WriteDouble(ref binary, offset, jr.DoubleValue);
                    }
                    else if (v == ValueType.Long)
                    {
                        offset += MessagePackBinary.WriteInt64(ref binary, offset, jr.LongValue);
                    }
                    else if (v == ValueType.ULong)
                    {
                        offset += MessagePackBinary.WriteUInt64(ref binary, offset, jr.ULongValue);
                    }
                    else if (v == ValueType.Decimal)
                    {
                        offset += DecimalFormatter.Instance.Serialize(ref binary, offset, jr.DecimalValue, null);
                    }
                    count++;
                    break;

                case TinyJsonToken.String:
                    offset += MessagePackBinary.WriteString(ref binary, offset, jr.StringValue);
                    count++;
                    break;

                case TinyJsonToken.True:
                    offset += MessagePackBinary.WriteBoolean(ref binary, offset, true);
                    count++;
                    break;

                case TinyJsonToken.False:
                    offset += MessagePackBinary.WriteBoolean(ref binary, offset, false);
                    count++;
                    break;

                case TinyJsonToken.Null:
                    offset += MessagePackBinary.WriteNil(ref binary, offset);
                    count++;
                    break;

                default:
                    break;
                }
            }
            return(count);
        }