public void WriteRepeated <T>(IReadOnlyCollection <T> values, RepeatedType <T> type) { // here we can check by one byte since wire type is mask and written in first byte // acually we can quick check by BaseType and don't store first byte, but // to support some strange non-packed primitive types... if (ProtoRepeatedInfo <T> .IsPackedRepeatedField(_tagFirstByte)) { // packed // fixed type? var fixedBaseSize = GetFixedBaseTypeSize(type.BaseType); if (fixedBaseSize == 0) { // variable field..., use same hack as in WriteMessage var current = _size; var write = type.WriteElement; var spot = MessageSizes.Reserve(); foreach (var value in values) { write(this, value); } var size = _size - current; // remember message size, we will need it _messageSizes.Set(spot, size); _size += VarIntHelper.GetVarInt32Size((uint)size); } else { // we can calculate message size fast and easy, no need to cache var size = fixedBaseSize * values.Count; _size += VarIntHelper.GetVarInt32Size((uint)size) + size; } } else { // don't cache non-packed sizes, they won't be asked // all the tag sizes _size += _lastTagSize * (values.Count - 1); var fixedBaseSize = GetFixedBaseTypeSize(type.BaseType); if (fixedBaseSize == 0) { var write = type.WriteElement; // write last tag foreach (var value in values) { write(this, value); } } else { _size += fixedBaseSize * values.Count; } } }
void IOutputStream.WriteMessage(IMessage message) { // we need to get individual message size here // to get message length varint size... var current = _size; var spot = MessageSizes.Reserve(); // just write it to this "stream" message.WriteTo(this); // ok, we have size, order doesn't matter ^^ var size = _size - current; // we can event cache it somewhere _messageSizes.Set(spot, size); // oh, and add length prefix to the "stream" _size += VarIntHelper.GetVarInt32Size((uint)size); }