A varint value is just bits until a type gives it meaning, and several protobuf scalars all ride the Varint wire type. Today you interpret one varint as a bool, an enum, and an int32, including the surprise that a negative int32 costs ten bytes.
Interpret a decoded varint as a bool, an enum, and a signed int32.
The Varint wire type is shared by a whole family of scalar types:
int32, int64, uint32, uint64, bool, and enum. On the wire they are all
just a varint; the schema decides how to read the bits. A bool is false when
the varint is 0 and true otherwise. An enum is stored exactly like an int32.
An unsigned value is the varint as-is. The interpretation is a cast, not a
different decode.
The sharp edge is a negative int32 or int64. Protobuf does not do anything
clever for plain signed types: a negative value is sign-extended to a full 64 bits
and then varint-encoded, so int32 -1 becomes ten 0xFF...0x01 bytes on the wire.
Reading it back gives a large unsigned value; casting its low 32 bits back to a
signed int32 recovers -1. This is wasteful for negative numbers, which is exactly
the problem the next lesson’s zigzag encoding solves. Pin the ten-byte encoding so
you know a negative int32 is never short.
func asBool(v uint64) bool { return v != 0 }func asEnum(v uint64) int32 { return int32(v) }func asInt32(v uint64) int32 { return int32(uint32(v)) } // low 32 bits// int64/uint32/uint64 are the same varint bits, just cast differently