internal static TLObjectWithExtra ReadRootObject(ReadOnlySpan <byte> input)
        {
            var reader = new TdJsonReader(input);

            var(obj, converter) = ConsumeObjectProlog(ref reader);
            var result = new TLObjectWithExtra()
            {
                TLObject = obj
            };
            var hasextra = false;

            while (reader.MoveToNextObjectMember())
            {
                var keystr = reader.ReadStringUTF8();
                reader.MoveToObjectMemberValue();
                if (!hasextra && keystr.SequenceEqual(@extra_bytes))
                {
                    result.Extra = reader.ReadInt64String();
                    hasextra     = true;
                    continue;
                }
                if (!converter.TdJsonReadItem(ref reader, obj, keystr))
                {
                    throw new TdJsonReaderException(reader.BytesConsumed, string.Format("unrecognized key {0} in type {1}", Encoding.UTF8.GetString(keystr), obj.GetType()));
                }
            }
            return(result);
        }
        private static (TLObject, BaseConverter) ConsumeObjectProlog(ref TdJsonReader reader)
        {
            if (!reader.BeginReadObject())
            {
                throw new TdJsonReaderException(reader.BytesConsumed, "object without @type");
            }
            var keystr = reader.ReadStringUTF8();

            if (!keystr.SequenceEqual(new ReadOnlySpan <byte>(new byte[] { 64, 116, 121, 112, 101 })))
            {
                throw new TdJsonReaderException(reader.BytesConsumed, "object without @type");
            }
            var token = reader.MoveToObjectMemberValue();

            if (token != TdJsonTokenType.String)
            {
                throw new TdJsonReaderException(reader.BytesConsumed, "object without @type");
            }
            var typestr  = reader.ReadStringUTF8();
            var typehash = Hash.ComputeHash(typestr);

            var converter = GetConverterForType(typehash);
            var obj       = converter.CreateObjectInstance();

            if (obj == null)
            {
                throw new JsonException(string.Format("cannot create object with type {0}", Encoding.UTF8.GetString(typestr.ToArray())));
            }
            return(obj, converter);
        }
        internal static TLObject ReadObject(ref TdJsonReader reader)
        {
            var(obj, converter) = ConsumeObjectProlog(ref reader);


            while (reader.MoveToNextObjectMember())
            {
                var keystr = reader.ReadStringUTF8();
                reader.MoveToObjectMemberValue();
                if (!converter.TdJsonReadItem(ref reader, obj, keystr))
                {
                    throw new TdJsonReaderException(reader.BytesConsumed, string.Format("unrecognized key {0} in type {1}", Encoding.UTF8.GetString(keystr), obj.GetType()));
                }
            }
            return(obj);
        }
 public virtual bool TdJsonReadItem(ref TdJsonReader reader, TLObject obj, ReadOnlySpan <byte> name) => false;