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; } } }
public void ReadRepeated <T>(AddRepeatedItem <T> addItem, RepeatedType <T> type, PrepareForRepeatedItems prepareForRepeatedItems = null) { var read = type.ReadElement; var tag = _lastTag; if (ProtoRepeatedInfo <T> .IsPackedRepeatedField(tag)) { // packed // read repeated size var totalSize = ReadByteSize(); if (totalSize <= 0) { return; } // try call prepare to add items if (prepareForRepeatedItems != null) { var fixedSize = ProtoSizeCalc.GetFixedBaseTypeSize(type.BaseType); if (fixedSize != 0) { var count = totalSize / fixedSize; prepareForRepeatedItems(count); } } // set length limit for this message var captureLength = SetView(totalSize); // end here will return view's end while (!End) { addItem(read(this)); } RestoreView(captureLength); } else { do { addItem(read(this)); } while (ReadTagIfEquals(tag)); } }
public void WriteRepeated <T>(IReadOnlyCollection <T> values, RepeatedType <T> type) { var tagBytes = _lastTagBytes; var tagStartPosition = CaptureCurrentPosition(tagBytes); // here we can check by one byte since wire type is mask and written in first byte if (ProtoRepeatedInfo <T> .IsPackedRepeatedField(Peek(tagStartPosition))) { // packed var size = _sizeCalc.GetRepeatedSize(values, type); WriteByteSize(size); if (size == 0) { return; } // trust message, don't set length-limit view var write = type.WriteElement; foreach (var value in values) { write(this, value); } } else { var write = type.WriteElement; var left = values.Count; foreach (var value in values) { write(this, value); left--; if (left == 0) { break; } // write last tag WriteCopy(tagStartPosition, tagBytes); } } }