public void AddEntriesFrom(ref ParseContext ctx, FieldCodec <T> codec) { // TODO: Inline some of the Add code, so we can avoid checking the size on every // iteration. uint tag = ctx.state.lastTag; var reader = codec.ValueReader; // Non-nullable value types can be packed or not. if (FieldCodec <T> .IsPackedRepeatedField(tag)) { int length = ctx.ReadLength(); if (length > 0) { int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); while (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) { Add(reader(ref ctx)); } SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); } // Empty packed field. Odd, but valid - just ignore. } else { // Not packed... (possibly not packable) do { Add(reader(ref ctx)); } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, tag)); } }
public void AddEntriesFrom(ref ParseContext ctx, FieldCodec <T> codec) { // TODO: Inline some of the Add code, so we can avoid checking the size on every // iteration. uint tag = ctx.state.lastTag; var reader = codec.ValueReader; // Non-nullable value types can be packed or not. if (FieldCodec <T> .IsPackedRepeatedField(tag)) { int length = ctx.ReadLength(); if (length > 0) { int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); // If the content is fixed size then we can calculate the length // of the repeated field and pre-initialize the underlying collection. // // Check that the supplied length doesn't exceed the underlying buffer. // That prevents a malicious length from initializing a very large collection. if (codec.FixedSize > 0 && length % codec.FixedSize == 0 && ParsingPrimitives.IsDataAvailable(ref ctx.state, length)) { EnsureSize(count + (length / codec.FixedSize)); while (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) { // Only FieldCodecs with a fixed size can reach here, and they are all known // types that don't allow the user to specify a custom reader action. // reader action will never return null. array[count++] = reader(ref ctx); } } else { // Content is variable size so add until we reach the limit. while (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) { Add(reader(ref ctx)); } } SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); } // Empty packed field. Odd, but valid - just ignore. } else { // Not packed... (possibly not packable) do { Add(reader(ref ctx)); } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, tag)); } }