encoding/cbor/encode.go (168 lines of code) (raw):

package cbor import ( "encoding/binary" "math" ) func (i Uint) len() int { return itoarglen(uint64(i)) } func (i Uint) encode(p []byte) int { return encodeArg(majorTypeUint, uint64(i), p) } func (i NegInt) len() int { return itoarglen(uint64(i) - 1) } func (i NegInt) encode(p []byte) int { return encodeArg(majorTypeNegInt, uint64(i-1), p) } func (s Slice) len() int { return itoarglen(len(s)) + len(s) } func (s Slice) encode(p []byte) int { off := encodeArg(majorTypeSlice, len(s), p) copy(p[off:], []byte(s)) return off + len(s) } func (s String) len() int { return itoarglen(len(s)) + len(s) } func (s String) encode(p []byte) int { off := encodeArg(majorTypeString, len(s), p) copy(p[off:], []byte(s)) return off + len(s) } func (l List) len() int { total := itoarglen(len(l)) for _, v := range l { total += v.len() } return total } func (l List) encode(p []byte) int { off := encodeArg(majorTypeList, len(l), p) for _, v := range l { off += v.encode(p[off:]) } return off } func (m Map) len() int { total := itoarglen(len(m)) for k, v := range m { total += String(k).len() + v.len() } return total } func (m Map) encode(p []byte) int { off := encodeArg(majorTypeMap, len(m), p) for k, v := range m { off += String(k).encode(p[off:]) off += v.encode(p[off:]) } return off } func (t Tag) len() int { return itoarglen(t.ID) + t.Value.len() } func (t Tag) encode(p []byte) int { off := encodeArg(majorTypeTag, t.ID, p) return off + t.Value.encode(p[off:]) } func (b Bool) len() int { return 1 } func (b Bool) encode(p []byte) int { if b { p[0] = compose(majorType7, major7True) } else { p[0] = compose(majorType7, major7False) } return 1 } func (*Nil) len() int { return 1 } func (*Nil) encode(p []byte) int { p[0] = compose(majorType7, major7Nil) return 1 } func (*Undefined) len() int { return 1 } func (*Undefined) encode(p []byte) int { p[0] = compose(majorType7, major7Undefined) return 1 } func (f Float32) len() int { return 5 } func (f Float32) encode(p []byte) int { p[0] = compose(majorType7, major7Float32) binary.BigEndian.PutUint32(p[1:], math.Float32bits(float32(f))) return 5 } func (f Float64) len() int { return 9 } func (f Float64) encode(p []byte) int { p[0] = compose(majorType7, major7Float64) binary.BigEndian.PutUint64(p[1:], math.Float64bits(float64(f))) return 9 } func compose(major majorType, minor byte) byte { return byte(major)<<5 | minor } func itoarglen[I int | uint64](v I) int { vv := uint64(v) if vv < 24 { return 1 // type and len in single byte } else if vv < 0x100 { return 2 // type + 1-byte len } else if vv < 0x10000 { return 3 // type + 2-byte len } else if vv < 0x100000000 { return 5 // type + 4-byte len } return 9 // type + 8-byte len } func encodeArg[I int | uint64](t majorType, arg I, p []byte) int { aarg := uint64(arg) if aarg < 24 { p[0] = byte(t)<<5 | byte(aarg) return 1 } else if aarg < 0x100 { p[0] = compose(t, minorArg1) p[1] = byte(aarg) return 2 } else if aarg < 0x10000 { p[0] = compose(t, minorArg2) binary.BigEndian.PutUint16(p[1:], uint16(aarg)) return 3 } else if aarg < 0x100000000 { p[0] = compose(t, minorArg4) binary.BigEndian.PutUint32(p[1:], uint32(aarg)) return 5 } p[0] = compose(t, minorArg8) binary.BigEndian.PutUint64(p[1:], uint64(aarg)) return 9 } // EncodeRaw encodes opaque CBOR data. // // This is used by the encoder for the purpose of embedding document shapes. // Decode will never return values of this type. type EncodeRaw []byte func (v EncodeRaw) len() int { return len(v) } func (v EncodeRaw) encode(p []byte) int { copy(p, v) return len(v) } // FixedUint encodes fixed-width Uint values. // // This is used by the encoder for the purpose of embedding integrals in // document shapes. Decode will never return values of this type. type EncodeFixedUint uint64 func (EncodeFixedUint) len() int { return 9 } func (v EncodeFixedUint) encode(p []byte) int { p[0] = compose(majorTypeUint, minorArg8) binary.BigEndian.PutUint64(p[1:], uint64(v)) return 9 } // FixedUint encodes fixed-width NegInt values. // // This is used by the encoder for the purpose of embedding integrals in // document shapes. Decode will never return values of this type. type EncodeFixedNegInt uint64 func (EncodeFixedNegInt) len() int { return 9 } func (v EncodeFixedNegInt) encode(p []byte) int { p[0] = compose(majorTypeNegInt, minorArg8) binary.BigEndian.PutUint64(p[1:], uint64(v-1)) return 9 }