package sarama import ( "encoding/binary" "fmt" "math" "github.com/rcrowley/go-metrics" ) type prepEncoder struct { stack []pushEncoder length int } // primitives func (pe *prepEncoder) putInt8(in int8) { pe.length++ } func (pe *prepEncoder) putInt16(in int16) { pe.length += 2 } func (pe *prepEncoder) putInt32(in int32) { pe.length += 4 } func (pe *prepEncoder) putInt64(in int64) { pe.length += 8 } func (pe *prepEncoder) putVarint(in int64) { var buf [binary.MaxVarintLen64]byte pe.length += binary.PutVarint(buf[:], in) } func (pe *prepEncoder) putArrayLength(in int) error { if in > math.MaxInt32 { return PacketEncodingError{fmt.Sprintf("array too long (%d)", in)} } pe.length += 4 return nil } func (pe *prepEncoder) putBool(in bool) { pe.length++ } // arrays func (pe *prepEncoder) putBytes(in []byte) error { pe.length += 4 if in == nil { return nil } return pe.putRawBytes(in) } func (pe *prepEncoder) putVarintBytes(in []byte) error { if in == nil { pe.putVarint(-1) return nil } pe.putVarint(int64(len(in))) return pe.putRawBytes(in) } func (pe *prepEncoder) putRawBytes(in []byte) error { if len(in) > math.MaxInt32 { return PacketEncodingError{fmt.Sprintf("byteslice too long (%d)", len(in))} } pe.length += len(in) return nil } func (pe *prepEncoder) putNullableString(in *string) error { if in == nil { pe.length += 2 return nil } return pe.putString(*in) } func (pe *prepEncoder) putString(in string) error { pe.length += 2 if len(in) > math.MaxInt16 { return PacketEncodingError{fmt.Sprintf("string too long (%d)", len(in))} } pe.length += len(in) return nil } func (pe *prepEncoder) putStringArray(in []string) error { err := pe.putArrayLength(len(in)) if err != nil { return err } for _, str := range in { if err := pe.putString(str); err != nil { return err } } return nil } func (pe *prepEncoder) putInt32Array(in []int32) error { err := pe.putArrayLength(len(in)) if err != nil { return err } pe.length += 4 * len(in) return nil } func (pe *prepEncoder) putInt64Array(in []int64) error { err := pe.putArrayLength(len(in)) if err != nil { return err } pe.length += 8 * len(in) return nil } func (pe *prepEncoder) offset() int { return pe.length } // stackable func (pe *prepEncoder) push(in pushEncoder) { in.saveOffset(pe.length) pe.length += in.reserveLength() pe.stack = append(pe.stack, in) } func (pe *prepEncoder) pop() error { in := pe.stack[len(pe.stack)-1] pe.stack = pe.stack[:len(pe.stack)-1] if dpe, ok := in.(dynamicPushEncoder); ok { pe.length += dpe.adjustLength(pe.length) } return nil } // we do not record metrics during the prep encoder pass func (pe *prepEncoder) metricRegistry() metrics.Registry { return nil }