예제 #1
0
        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;
                }
            }
        }
예제 #2
0
        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));
            }
        }
예제 #3
0
        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);
                }
            }
        }
예제 #4
0
        public int GetRepeatedSize <T>(IReadOnlyCollection <T> values, RepeatedType <T> type)
        {
            if (values == null || values.Count == 0)
            {
                return(0);
            }
            var fixedBaseSize = GetFixedBaseTypeSize(type.BaseType);

            if (fixedBaseSize != 0)
            {
                return(fixedBaseSize * values.Count);
            }

            //if (_cache)
            //{
            if (_messageSizes == null)
            {
                throw NoCalcMessagesException();
            }
            // we can cachy by collection only since Repeated type has no out-of-lib configuration
            var size = _messageSizes.Get();

            if (size < 0)
            {
                throw new InvalidOperationException("Root message doesn't had passed repeated field");
            }
            return(size);
            //}
            //// no cache, calculate always
            //var captureSize = _size;
            //_size = 0;
            //WriteRepeated(values, type);
            //var result = _size;
            //_size = captureSize;
            //return result;
        }