package capnp import ( "errors" "math" "strconv" "zombiezen.com/go/capnproto2/internal/strquote" ) // A List is a reference to an array of values. type List struct { seg *Segment off Address // at beginning of elements (past composite list tag word) length int32 size ObjectSize depthLimit uint flags listFlags } // newPrimitiveList allocates a new list of primitive values, preferring placement in s. func newPrimitiveList(s *Segment, sz Size, n int32) (List, error) { total, ok := sz.times(n) if !ok { return List{}, errOverflow } s, addr, err := alloc(s, total) if err != nil { return List{}, err } return List{ seg: s, off: addr, length: n, size: ObjectSize{DataSize: sz}, depthLimit: maxDepth, }, nil } // NewCompositeList creates a new composite list, preferring placement // in s. func NewCompositeList(s *Segment, sz ObjectSize, n int32) (List, error) { if !sz.isValid() { return List{}, errObjectSize } sz.DataSize = sz.DataSize.padToWord() total, ok := sz.totalSize().times(n) if !ok || total > maxSize-wordSize { return List{}, errOverflow } s, addr, err := alloc(s, wordSize+total) if err != nil { return List{}, err } // Add tag word s.writeRawPointer(addr, rawStructPointer(pointerOffset(n), sz)) return List{ seg: s, off: addr + Address(wordSize), length: n, size: sz, flags: isCompositeList, depthLimit: maxDepth, }, nil } // ToList converts p to a List. // // Deprecated: Use Ptr.List. func ToList(p Pointer) List { return toPtr(p).List() } // ToListDefault attempts to convert p into a list, reading the default // value from def if p is not a list. // // Deprecated: Use Ptr.ListDefault. func ToListDefault(p Pointer, def []byte) (List, error) { return toPtr(p).ListDefault(def) } // ToPtr converts the list to a generic pointer. func (p List) ToPtr() Ptr { return Ptr{ seg: p.seg, off: p.off, lenOrCap: uint32(p.length), size: p.size, depthLimit: p.depthLimit, flags: listPtrFlag(p.flags), } } // Segment returns the segment this pointer references. func (p List) Segment() *Segment { return p.seg } // IsValid returns whether the list is valid. func (p List) IsValid() bool { return p.seg != nil } // HasData reports whether the list's total size is non-zero. func (p List) HasData() bool { sz, ok := p.size.totalSize().times(p.length) if !ok { return false } return sz > 0 } // readSize returns the list's size for the purposes of read limit // accounting. func (p List) readSize() Size { if p.seg == nil { return 0 } e := p.size.totalSize() if e == 0 { e = wordSize } sz, ok := e.times(p.length) if !ok { return maxSize } return sz } // allocSize returns the list's size for the purpose of copying the list // to a different message. func (p List) allocSize() Size { if p.seg == nil { return 0 } if p.flags&isBitList != 0 { return Size((p.length + 7) / 8) } sz, _ := p.size.totalSize().times(p.length) // size has already been validated if p.flags&isCompositeList == 0 { return sz } return sz + wordSize } // raw returns the equivalent raw list pointer with a zero offset. func (p List) raw() rawPointer { if p.seg == nil { return 0 } if p.flags&isCompositeList != 0 { return rawListPointer(0, compositeList, p.length*p.size.totalWordCount()) } if p.flags&isBitList != 0 { return rawListPointer(0, bit1List, p.length) } if p.size.PointerCount == 1 && p.size.DataSize == 0 { return rawListPointer(0, pointerList, p.length) } if p.size.PointerCount != 0 { panic(errListSize) } switch p.size.DataSize { case 0: return rawListPointer(0, voidList, p.length) case 1: return rawListPointer(0, byte1List, p.length) case 2: return rawListPointer(0, byte2List, p.length) case 4: return rawListPointer(0, byte4List, p.length) case 8: return rawListPointer(0, byte8List, p.length) default: panic(errListSize) } } func (p List) underlying() Pointer { return p } // Address returns the address the pointer references. // // Deprecated: The return value is not well-defined. Use SamePtr if you // need to check whether two pointers refer to the same object. func (p List) Address() Address { return p.off } // Len returns the length of the list. func (p List) Len() int { if p.seg == nil { return 0 } return int(p.length) } // primitiveElem returns the address of the segment data for a list element. // Calling this on a bit list returns an error. func (p List) primitiveElem(i int, expectedSize ObjectSize) (Address, error) { if p.seg == nil || i < 0 || i >= int(p.length) { // This is programmer error, not input error. panic(errOutOfBounds) } if p.flags&isBitList != 0 || p.flags&isCompositeList == 0 && p.size != expectedSize || p.flags&isCompositeList != 0 && (p.size.DataSize < expectedSize.DataSize || p.size.PointerCount < expectedSize.PointerCount) { return 0, errElementSize } addr, ok := p.off.element(int32(i), p.size.totalSize()) if !ok { return 0, errOverflow } return addr, nil } // Struct returns the i'th element as a struct. func (p List) Struct(i int) Struct { if p.seg == nil || i < 0 || i >= int(p.length) { // This is programmer error, not input error. panic(errOutOfBounds) } if p.flags&isBitList != 0 { return Struct{} } addr, ok := p.off.element(int32(i), p.size.totalSize()) if !ok { return Struct{} } return Struct{ seg: p.seg, off: addr, size: p.size, flags: isListMember, depthLimit: p.depthLimit - 1, } } // SetStruct set the i'th element to the value in s. func (p List) SetStruct(i int, s Struct) error { if p.flags&isBitList != 0 { return errBitListStruct } return copyStruct(p.Struct(i), s) } // A BitList is a reference to a list of booleans. type BitList struct{ List } // NewBitList creates a new bit list, preferring placement in s. func NewBitList(s *Segment, n int32) (BitList, error) { s, addr, err := alloc(s, Size(int64(n+7)/8)) if err != nil { return BitList{}, err } return BitList{List{ seg: s, off: addr, length: n, flags: isBitList, depthLimit: maxDepth, }}, nil } // At returns the i'th bit. func (p BitList) At(i int) bool { if p.seg == nil || i < 0 || i >= int(p.length) { // This is programmer error, not input error. panic(errOutOfBounds) } if p.flags&isBitList == 0 { return false } bit := BitOffset(i) addr := p.off.addOffset(bit.offset()) return p.seg.readUint8(addr)&bit.mask() != 0 } // Set sets the i'th bit to v. func (p BitList) Set(i int, v bool) { if p.seg == nil || i < 0 || i >= int(p.length) { // This is programmer error, not input error. panic(errOutOfBounds) } if p.flags&isBitList == 0 { // Again, programmer error. Should have used NewBitList. panic(errElementSize) } bit := BitOffset(i) addr := p.off.addOffset(bit.offset()) b := p.seg.slice(addr, 1) if v { b[0] |= bit.mask() } else { b[0] &^= bit.mask() } } // String returns the list in Cap'n Proto schema format (e.g. "[true, false]"). func (p BitList) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < p.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } if p.At(i) { buf = append(buf, "true"...) } else { buf = append(buf, "false"...) } } buf = append(buf, ']') return string(buf) } // A PointerList is a reference to an array of pointers. type PointerList struct{ List } // NewPointerList allocates a new list of pointers, preferring placement in s. func NewPointerList(s *Segment, n int32) (PointerList, error) { total, ok := wordSize.times(n) if !ok { return PointerList{}, errOverflow } s, addr, err := alloc(s, total) if err != nil { return PointerList{}, err } return PointerList{List{ seg: s, off: addr, length: n, size: ObjectSize{PointerCount: 1}, depthLimit: maxDepth, }}, nil } // At returns the i'th pointer in the list. // // Deprecated: Use PtrAt. func (p PointerList) At(i int) (Pointer, error) { pi, err := p.PtrAt(i) return pi.toPointer(), err } // PtrAt returns the i'th pointer in the list. func (p PointerList) PtrAt(i int) (Ptr, error) { addr, err := p.primitiveElem(i, ObjectSize{PointerCount: 1}) if err != nil { return Ptr{}, err } return p.seg.readPtr(addr, p.depthLimit) } // Set sets the i'th pointer in the list to v. // // Deprecated: Use SetPtr. func (p PointerList) Set(i int, v Pointer) error { return p.SetPtr(i, toPtr(v)) } // SetPtr sets the i'th pointer in the list to v. func (p PointerList) SetPtr(i int, v Ptr) error { addr, err := p.primitiveElem(i, ObjectSize{PointerCount: 1}) if err != nil { return err } return p.seg.writePtr(addr, v, false) } // TextList is an array of pointers to strings. type TextList struct{ List } // NewTextList allocates a new list of text pointers, preferring placement in s. func NewTextList(s *Segment, n int32) (TextList, error) { pl, err := NewPointerList(s, n) if err != nil { return TextList{}, err } return TextList{pl.List}, nil } // At returns the i'th string in the list. func (l TextList) At(i int) (string, error) { addr, err := l.primitiveElem(i, ObjectSize{PointerCount: 1}) if err != nil { return "", err } p, err := l.seg.readPtr(addr, l.depthLimit) if err != nil { return "", err } return p.Text(), nil } // BytesAt returns the i'th element in the list as a byte slice. // The underlying array of the slice is the segment data. func (l TextList) BytesAt(i int) ([]byte, error) { addr, err := l.primitiveElem(i, ObjectSize{PointerCount: 1}) if err != nil { return nil, err } p, err := l.seg.readPtr(addr, l.depthLimit) if err != nil { return nil, err } return p.TextBytes(), nil } // Set sets the i'th string in the list to v. func (l TextList) Set(i int, v string) error { addr, err := l.primitiveElem(i, ObjectSize{PointerCount: 1}) if err != nil { return err } if v == "" { return l.seg.writePtr(addr, Ptr{}, false) } p, err := NewText(l.seg, v) if err != nil { return err } return l.seg.writePtr(addr, p.List.ToPtr(), false) } // String returns the list in Cap'n Proto schema format (e.g. `["foo", "bar"]`). func (l TextList) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } s, err := l.BytesAt(i) if err != nil { buf = append(buf, "<error>"...) continue } buf = strquote.Append(buf, s) } buf = append(buf, ']') return string(buf) } // DataList is an array of pointers to data. type DataList struct{ List } // NewDataList allocates a new list of data pointers, preferring placement in s. func NewDataList(s *Segment, n int32) (DataList, error) { pl, err := NewPointerList(s, n) if err != nil { return DataList{}, err } return DataList{pl.List}, nil } // At returns the i'th data in the list. func (l DataList) At(i int) ([]byte, error) { addr, err := l.primitiveElem(i, ObjectSize{PointerCount: 1}) if err != nil { return nil, err } p, err := l.seg.readPtr(addr, l.depthLimit) if err != nil { return nil, err } return p.Data(), nil } // Set sets the i'th data in the list to v. func (l DataList) Set(i int, v []byte) error { addr, err := l.primitiveElem(i, ObjectSize{PointerCount: 1}) if err != nil { return err } if len(v) == 0 { return l.seg.writePtr(addr, Ptr{}, false) } p, err := NewData(l.seg, v) if err != nil { return err } return l.seg.writePtr(addr, p.List.ToPtr(), false) } // String returns the list in Cap'n Proto schema format (e.g. `["foo", "bar"]`). func (l DataList) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } s, err := l.At(i) if err != nil { buf = append(buf, "<error>"...) continue } buf = strquote.Append(buf, s) } buf = append(buf, ']') return string(buf) } // A VoidList is a list of zero-sized elements. type VoidList struct{ List } // NewVoidList creates a list of voids. No allocation is performed; // s is only used for Segment()'s return value. func NewVoidList(s *Segment, n int32) VoidList { return VoidList{List{ seg: s, length: n, depthLimit: maxDepth, }} } // String returns the list in Cap'n Proto schema format (e.g. "[void, void, void]"). func (l VoidList) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = append(buf, "void"...) } buf = append(buf, ']') return string(buf) } // A UInt8List is an array of UInt8 values. type UInt8List struct{ List } // NewUInt8List creates a new list of UInt8, preferring placement in s. func NewUInt8List(s *Segment, n int32) (UInt8List, error) { l, err := newPrimitiveList(s, 1, n) if err != nil { return UInt8List{}, err } return UInt8List{l}, nil } // NewText creates a new list of UInt8 from a string. func NewText(s *Segment, v string) (UInt8List, error) { // TODO(light): error if v is too long l, err := NewUInt8List(s, int32(len(v)+1)) if err != nil { return UInt8List{}, err } copy(l.seg.slice(l.off, Size(len(v))), v) return l, nil } // NewTextFromBytes creates a NUL-terminated list of UInt8 from a byte slice. func NewTextFromBytes(s *Segment, v []byte) (UInt8List, error) { // TODO(light): error if v is too long l, err := NewUInt8List(s, int32(len(v)+1)) if err != nil { return UInt8List{}, err } copy(l.seg.slice(l.off, Size(len(v))), v) return l, nil } // NewData creates a new list of UInt8 from a byte slice. func NewData(s *Segment, v []byte) (UInt8List, error) { // TODO(light): error if v is too long l, err := NewUInt8List(s, int32(len(v))) if err != nil { return UInt8List{}, err } copy(l.seg.slice(l.off, Size(len(v))), v) return l, nil } // ToText attempts to convert p into Text. // // Deprecated: Use Ptr.Text. func ToText(p Pointer) string { return toPtr(p).TextDefault("") } // ToTextDefault attempts to convert p into Text, returning def on failure. // // Deprecated: Use Ptr.TextDefault. func ToTextDefault(p Pointer, def string) string { return toPtr(p).TextDefault(def) } // ToData attempts to convert p into Data. // // Deprecated: Use Ptr.Data. func ToData(p Pointer) []byte { return toPtr(p).DataDefault(nil) } // ToDataDefault attempts to convert p into Data, returning def on failure. // // Deprecated: Use Ptr.DataDefault. func ToDataDefault(p Pointer, def []byte) []byte { return toPtr(p).DataDefault(def) } func isOneByteList(p Ptr) bool { return p.seg != nil && p.flags.ptrType() == listPtrType && p.size.isOneByte() && p.flags.listFlags()&isCompositeList == 0 } // At returns the i'th element. func (l UInt8List) At(i int) uint8 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 1}) if err != nil { return 0 } return l.seg.readUint8(addr) } // Set sets the i'th element to v. func (l UInt8List) Set(i int, v uint8) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 1}) if err != nil { panic(err) } l.seg.writeUint8(addr, v) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l UInt8List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendUint(buf, uint64(l.At(i)), 10) } buf = append(buf, ']') return string(buf) } // Int8List is an array of Int8 values. type Int8List struct{ List } // NewInt8List creates a new list of Int8, preferring placement in s. func NewInt8List(s *Segment, n int32) (Int8List, error) { l, err := newPrimitiveList(s, 1, n) if err != nil { return Int8List{}, err } return Int8List{l}, nil } // At returns the i'th element. func (l Int8List) At(i int) int8 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 1}) if err != nil { return 0 } return int8(l.seg.readUint8(addr)) } // Set sets the i'th element to v. func (l Int8List) Set(i int, v int8) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 1}) if err != nil { panic(err) } l.seg.writeUint8(addr, uint8(v)) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l Int8List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendInt(buf, int64(l.At(i)), 10) } buf = append(buf, ']') return string(buf) } // A UInt16List is an array of UInt16 values. type UInt16List struct{ List } // NewUInt16List creates a new list of UInt16, preferring placement in s. func NewUInt16List(s *Segment, n int32) (UInt16List, error) { l, err := newPrimitiveList(s, 2, n) if err != nil { return UInt16List{}, err } return UInt16List{l}, nil } // At returns the i'th element. func (l UInt16List) At(i int) uint16 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 2}) if err != nil { return 0 } return l.seg.readUint16(addr) } // Set sets the i'th element to v. func (l UInt16List) Set(i int, v uint16) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 2}) if err != nil { panic(err) } l.seg.writeUint16(addr, v) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l UInt16List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendUint(buf, uint64(l.At(i)), 10) } buf = append(buf, ']') return string(buf) } // Int16List is an array of Int16 values. type Int16List struct{ List } // NewInt16List creates a new list of Int16, preferring placement in s. func NewInt16List(s *Segment, n int32) (Int16List, error) { l, err := newPrimitiveList(s, 2, n) if err != nil { return Int16List{}, err } return Int16List{l}, nil } // At returns the i'th element. func (l Int16List) At(i int) int16 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 2}) if err != nil { return 0 } return int16(l.seg.readUint16(addr)) } // Set sets the i'th element to v. func (l Int16List) Set(i int, v int16) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 2}) if err != nil { panic(err) } l.seg.writeUint16(addr, uint16(v)) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l Int16List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendInt(buf, int64(l.At(i)), 10) } buf = append(buf, ']') return string(buf) } // UInt32List is an array of UInt32 values. type UInt32List struct{ List } // NewUInt32List creates a new list of UInt32, preferring placement in s. func NewUInt32List(s *Segment, n int32) (UInt32List, error) { l, err := newPrimitiveList(s, 4, n) if err != nil { return UInt32List{}, err } return UInt32List{l}, nil } // At returns the i'th element. func (l UInt32List) At(i int) uint32 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 4}) if err != nil { return 0 } return l.seg.readUint32(addr) } // Set sets the i'th element to v. func (l UInt32List) Set(i int, v uint32) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 4}) if err != nil { panic(err) } l.seg.writeUint32(addr, v) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l UInt32List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendUint(buf, uint64(l.At(i)), 10) } buf = append(buf, ']') return string(buf) } // Int32List is an array of Int32 values. type Int32List struct{ List } // NewInt32List creates a new list of Int32, preferring placement in s. func NewInt32List(s *Segment, n int32) (Int32List, error) { l, err := newPrimitiveList(s, 4, n) if err != nil { return Int32List{}, err } return Int32List{l}, nil } // At returns the i'th element. func (l Int32List) At(i int) int32 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 4}) if err != nil { return 0 } return int32(l.seg.readUint32(addr)) } // Set sets the i'th element to v. func (l Int32List) Set(i int, v int32) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 4}) if err != nil { panic(err) } l.seg.writeUint32(addr, uint32(v)) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l Int32List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendInt(buf, int64(l.At(i)), 10) } buf = append(buf, ']') return string(buf) } // UInt64List is an array of UInt64 values. type UInt64List struct{ List } // NewUInt64List creates a new list of UInt64, preferring placement in s. func NewUInt64List(s *Segment, n int32) (UInt64List, error) { l, err := newPrimitiveList(s, 8, n) if err != nil { return UInt64List{}, err } return UInt64List{l}, nil } // At returns the i'th element. func (l UInt64List) At(i int) uint64 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 8}) if err != nil { return 0 } return l.seg.readUint64(addr) } // Set sets the i'th element to v. func (l UInt64List) Set(i int, v uint64) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 8}) if err != nil { panic(err) } l.seg.writeUint64(addr, v) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l UInt64List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendUint(buf, l.At(i), 10) } buf = append(buf, ']') return string(buf) } // Int64List is an array of Int64 values. type Int64List struct{ List } // NewInt64List creates a new list of Int64, preferring placement in s. func NewInt64List(s *Segment, n int32) (Int64List, error) { l, err := newPrimitiveList(s, 8, n) if err != nil { return Int64List{}, err } return Int64List{l}, nil } // At returns the i'th element. func (l Int64List) At(i int) int64 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 8}) if err != nil { return 0 } return int64(l.seg.readUint64(addr)) } // Set sets the i'th element to v. func (l Int64List) Set(i int, v int64) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 8}) if err != nil { panic(err) } l.seg.writeUint64(addr, uint64(v)) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l Int64List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendInt(buf, l.At(i), 10) } buf = append(buf, ']') return string(buf) } // Float32List is an array of Float32 values. type Float32List struct{ List } // NewFloat32List creates a new list of Float32, preferring placement in s. func NewFloat32List(s *Segment, n int32) (Float32List, error) { l, err := newPrimitiveList(s, 4, n) if err != nil { return Float32List{}, err } return Float32List{l}, nil } // At returns the i'th element. func (l Float32List) At(i int) float32 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 4}) if err != nil { return 0 } return math.Float32frombits(l.seg.readUint32(addr)) } // Set sets the i'th element to v. func (l Float32List) Set(i int, v float32) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 4}) if err != nil { panic(err) } l.seg.writeUint32(addr, math.Float32bits(v)) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l Float32List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendFloat(buf, float64(l.At(i)), 'g', -1, 32) } buf = append(buf, ']') return string(buf) } // Float64List is an array of Float64 values. type Float64List struct{ List } // NewFloat64List creates a new list of Float64, preferring placement in s. func NewFloat64List(s *Segment, n int32) (Float64List, error) { l, err := newPrimitiveList(s, 8, n) if err != nil { return Float64List{}, err } return Float64List{l}, nil } // At returns the i'th element. func (l Float64List) At(i int) float64 { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 8}) if err != nil { return 0 } return math.Float64frombits(l.seg.readUint64(addr)) } // Set sets the i'th element to v. func (l Float64List) Set(i int, v float64) { addr, err := l.primitiveElem(i, ObjectSize{DataSize: 8}) if err != nil { panic(err) } l.seg.writeUint64(addr, math.Float64bits(v)) } // String returns the list in Cap'n Proto schema format (e.g. "[1, 2, 3]"). func (l Float64List) String() string { var buf []byte buf = append(buf, '[') for i := 0; i < l.Len(); i++ { if i > 0 { buf = append(buf, ", "...) } buf = strconv.AppendFloat(buf, l.At(i), 'g', -1, 64) } buf = append(buf, ']') return string(buf) } type listFlags uint8 const ( isCompositeList listFlags = 1 << iota isBitList ) var errBitListStruct = errors.New("capnp: SetStruct called on bit list")