@Override boolean readLengthPrefixAndValue(ReadBuffer b, Span.Builder builder) {
      int length = b.readVarint32();
      if (length == 0) return false;
      int endPos = b.pos() + length;

      // now, we are in the tag fields
      String key = null, value = ""; // empty tags allowed
      while (b.pos() < endPos) {
        int nextKey = b.readVarint32();
        switch (nextKey) {
          case KEY_KEY:
            key = KEY.readLengthPrefixAndValue(b);
            break;
          case VALUE_KEY:
            String read = VALUE.readLengthPrefixAndValue(b);
            if (read != null) value = read; // empty tags allowed
            break;
          default:
            logAndSkip(b, nextKey);
        }
      }
      if (key == null) return false;
      builder.putTag(key, value);
      return true;
    }
Contributes to a builder as opposed to reading values directly. Avoids allocation.
zipkin/src/main/java/zipkin2/internal/Proto3ZipkinFields.java