// Name returns a view of the name. Caller must not keep references to // it past the lifetime of the view. // // If the message is truncated, returns an empty string. func (v *PersonV2View) Name() string { l, n := varuint.Uint64(v.data[slotsLenPersonV2View:]) if n < 0 { return "" } if l == 0 { panic("TODO padding not handled yet") } l-- const maxInt = int(^uint(0) >> 1) if l > uint64(maxInt) { // technically, it has to be truncated because it wouldn't fit // in memory ;) return "" } end := slotsLenPersonV2View + n + int(l) if end > len(v.data) { return "" } var s string p := (*reflect.StringHeader)(unsafe.Pointer(&s)) p.Data = uintptr(unsafe.Pointer(&v.data[slotsLenPersonV2View+n])) p.Len = int(l) return s }
// Next returns the contents of the next frame. // // Returns io.EOF if there are no more frames. Returns // io.ErrUnexpectedEOF on truncated data. func (v *FramedView) Next() ([]byte, error) { loop: if len(v.data) == 0 { return nil, io.EOF } l, n := varuint.Uint64(v.data) if n < 0 { return nil, io.ErrUnexpectedEOF } if l == 0 { goto loop } l-- const maxInt = int(^uint(0) >> 1) if l > uint64(maxInt) { // technically, it has to be truncated because it wouldn't fit // in memory ;) return nil, io.ErrUnexpectedEOF } end := n + int(l) if end > len(v.data) { return nil, io.ErrUnexpectedEOF } b := v.data[n:end] v.data = v.data[end:] return b, nil }
func chitinParseLengthPrefixed(data []byte) (msg []byte, next []byte, err error) { loop: l, n := varuint.Uint64(data) if n < 0 { return nil, nil, io.ErrUnexpectedEOF } if l == 0 { // padding data = data[n:] goto loop } l-- const maxInt = int(^uint(0) >> 1) if l > uint64(maxInt) { // technically, it has to be truncated because it wouldn't fit // in memory ;) return nil, nil, io.ErrUnexpectedEOF } li := int(l) // TODO prevent overflow here end := n + li if end > len(data) { return nil, nil, io.ErrUnexpectedEOF } low := n high := low + li return data[low:high], data[high:], nil }
func BenchmarkDchestUint64MaxLen(b *testing.B) { var res uint64 b.SetBytes(8) for i := 0; i < b.N; i++ { res, _ = varuint.Uint64(tests[17].encoded) } _ = res }
func BenchmarkDchestUint64All(b *testing.B) { var res uint64 b.SetBytes(8) for i := 0; i < b.N; i++ { for _, test := range tests { res, _ = varuint.Uint64(test.encoded) } } _ = res }
func NewMyProtocolView(data []byte) (MyProtocolMessage, error) { if len(data) == 0 { return nil, chitin.ErrWrongSize } kind, n := varuint.Uint64(data) if n < 0 { return nil, chitin.ErrWrongSize } data = data[n:] switch kind { default: return nil, chitin.ErrUnknownMessageKind case 0: return nil, chitin.ErrIsPadding case 1: return NewPersonV2View(data) } }
func TestVaruint(t *testing.T) { for i, test := range tests { b := make([]byte, len(test.encoded)) n := varuint.PutUint64(b, test.decoded) if n != test.n { t.Errorf("encode %d: got %d want %d", i, n, test.n) } if !bytes.Equal(b, test.encoded) { t.Errorf("encode %d: got %v want %v", i, b[0:n], test.encoded) } v, n := varuint.Uint64(test.encoded) if n != test.n { t.Errorf("decode %d: got %d want %d", i, n, test.n) } if v != test.decoded { t.Errorf("decode %d: got %d want %d", i, v, test.decoded) } } }