static object ParseSingleVarint(IPrimitiveField.Types type, Stream stream, ulong max_len, out ulong length) { switch (type) { case IPrimitiveField.Types.Bool: return(Varint.FromBase128(stream, max_len, out length) != 0); case IPrimitiveField.Types.Int32: return((int)Varint.FromBase128Signed(stream, max_len, out length)); case IPrimitiveField.Types.Int64: return((long)Varint.FromBase128Signed(stream, max_len, out length)); case IPrimitiveField.Types.Uint32: return((uint)Varint.FromBase128(stream, max_len, out length)); case IPrimitiveField.Types.Uint64: return((ulong)Varint.FromBase128(stream, max_len, out length)); default: throw new InvalidOperationException("This function can only parse values from varints"); } }
static void ParseClass(IClass cls, Stream stream, long allowed_length = -1) { // How do I want to deal with invalid stuff? if (allowed_length < 0) { allowed_length = stream.Length; } bool done = false; try { while (stream.Position != allowed_length && !done) { Tuple <int, WireType> fieldInfo = ReadFieldInfo(stream); WireType wireType = fieldInfo.Item2; int fieldNum = fieldInfo.Item1; IField field = cls.Fields.Where((field) => { return(field.Number == fieldNum); }).SingleOrDefault(); if (field == null) { // Discard this field DiscardWire(wireType, stream); continue; } switch (field) { case IClassField classField: DiscardIfNot(stream, WireType.LENGTH_DELIMITED, wireType, () => { ulong length = Varint.FromBase128(stream); AppendIfList(classField); ParseClass(classField[classField.Count - 1], stream, stream.Position + (long)length); }); break; case IEnumField enumField: Func <ulong, ulong> addOneEnum = (max_len) => { AppendIfList(enumField); enumField[enumField.Count - 1] = (int)Varint.FromBase128(stream, max_len, out ulong length); return(length); }; if (wireType == WireType.LENGTH_DELIMITED) { ulong length = Varint.FromBase128(stream); for (ulong i = 0; i < length;) { i += addOneEnum(length - i); } } else { DiscardIfNot(stream, WireType.VARINT, wireType, () => { addOneEnum(10); }); } break; case IPrimitiveField primitiveField: IPrimitiveField.Types fieldType = primitiveField.Type; switch (fieldType) { case IPrimitiveField.Types.Bool: case IPrimitiveField.Types.Int32: case IPrimitiveField.Types.Int64: case IPrimitiveField.Types.Uint32: case IPrimitiveField.Types.Uint64: Func <ulong, ulong> addOnePrim = (max_len) => { AppendIfList(primitiveField); primitiveField[primitiveField.Count - 1] = ParseSingleVarint(fieldType, stream, max_len, out ulong length); return(length); }; if (wireType == WireType.LENGTH_DELIMITED) { ulong length = Varint.FromBase128(stream); for (ulong i = 0; i < length;) { i += addOnePrim(length - i); } ; } else { DiscardIfNot(stream, WireType.VARINT, wireType, () => { addOnePrim(10); }); } break; case IPrimitiveField.Types.Double: DiscardIfNot(stream, WireType.FIXED_64, wireType, () => { AppendIfList(primitiveField); primitiveField[primitiveField.Count - 1] = new BinaryReader(stream).ReadDouble(); }); break; case IPrimitiveField.Types.Float: DiscardIfNot(stream, WireType.FIXED_32, wireType, () => { AppendIfList(primitiveField); primitiveField[primitiveField.Count - 1] = new BinaryReader(stream).ReadSingle(); }); break; case IPrimitiveField.Types.String: DiscardIfNot(stream, WireType.LENGTH_DELIMITED, wireType, () => { ulong length = Varint.FromBase128(stream); StringWriter stringWriter = new(); for (ulong i = 0; i < length; i++) { stringWriter.Write((char)stream.ReadByte()); } AppendIfList(primitiveField); primitiveField[primitiveField.Count - 1] = stringWriter.ToString(); }); break; } ; break; } } } catch (EndOfStreamException) { } }
static object ParseSingleVarint(IPrimitiveField.Types type, Stream stream, ulong max_len = 10) => ParseSingleVarint(type, stream, max_len, out _);