@Override public void write(Span value, WriteBuffer buffer) {
    V1Span v1Span = converter.convert(value);
    byte[] endpointBytes = legacyEndpointBytes(value.localEndpoint());

    TRACE_ID.write(buffer);
    ThriftCodec.writeLong(buffer, v1Span.traceId());

    NAME.write(buffer);
    ThriftCodec.writeLengthPrefixed(buffer, value.name() != null ? value.name() : "");

    ID.write(buffer);
    ThriftCodec.writeLong(buffer, v1Span.id());

    if (v1Span.parentId() != 0L) {
      PARENT_ID.write(buffer);
      ThriftCodec.writeLong(buffer, v1Span.parentId());
    }

    // we write list thriftFields even when empty to match finagle serialization
    ANNOTATIONS.write(buffer);
    writeAnnotations(buffer, v1Span, endpointBytes);

    BINARY_ANNOTATIONS.write(buffer);
    writeBinaryAnnotations(buffer, v1Span, endpointBytes);

    if (v1Span.debug() != null) {
      DEBUG.write(buffer);
      buffer.writeByte(v1Span.debug() ? 1 : 0);
    }

    if (v1Span.timestamp() != 0L) {
      TIMESTAMP.write(buffer);
      ThriftCodec.writeLong(buffer, v1Span.timestamp());
    }
    if (v1Span.duration() != 0L) {
      DURATION.write(buffer);
      ThriftCodec.writeLong(buffer, v1Span.duration());
    }

    if (v1Span.traceIdHigh() != 0L) {
      TRACE_ID_HIGH.write(buffer);
      ThriftCodec.writeLong(buffer, v1Span.traceIdHigh());
    }

    buffer.writeByte(TYPE_STOP);
  }
This type isn't thread-safe: it re-uses state to avoid re-allocations in conversion loops.
zipkin/src/main/java/zipkin2/internal/V1ThriftSpanWriter.java