diff options
author | Runxi Yu <me@runxiyu.org> | 2025-08-17 03:09:52 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2025-08-17 03:09:52 +0800 |
commit | 009a6e397651a9540b6c6bb74ef2230eeda9b577 (patch) | |
tree | 0a808670d95aba5804a73a558cc335a49d230aa6 /forged/internal/bare | |
parent | Remove HTML templates from main server (diff) | |
download | forge-009a6e397651a9540b6c6bb74ef2230eeda9b577.tar.gz forge-009a6e397651a9540b6c6bb74ef2230eeda9b577.tar.zst forge-009a6e397651a9540b6c6bb74ef2230eeda9b577.zip |
Some mass renaming
Diffstat (limited to 'forged/internal/bare')
-rw-r--r-- | forged/internal/bare/doc.go | 8 | ||||
-rw-r--r-- | forged/internal/bare/errors.go | 20 | ||||
-rw-r--r-- | forged/internal/bare/limit.go | 58 | ||||
-rw-r--r-- | forged/internal/bare/marshal.go | 311 | ||||
-rw-r--r-- | forged/internal/bare/reader.go | 190 | ||||
-rw-r--r-- | forged/internal/bare/unions.go | 79 | ||||
-rw-r--r-- | forged/internal/bare/unmarshal.go | 362 | ||||
-rw-r--r-- | forged/internal/bare/varint.go | 30 | ||||
-rw-r--r-- | forged/internal/bare/writer.go | 121 |
9 files changed, 0 insertions, 1179 deletions
diff --git a/forged/internal/bare/doc.go b/forged/internal/bare/doc.go deleted file mode 100644 index 2f12f55..0000000 --- a/forged/internal/bare/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> - -// Package bare provides primitives to encode and decode BARE messages. -// -// There is no guarantee that this is compatible with the upstream -// implementation at https://git.sr.ht/~sircmpwn/go-bare. -package bare diff --git a/forged/internal/bare/errors.go b/forged/internal/bare/errors.go deleted file mode 100644 index 39c951a..0000000 --- a/forged/internal/bare/errors.go +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Drew Devault <https://drewdevault.com> - -package bare - -import ( - "errors" - "fmt" - "reflect" -) - -var ErrInvalidStr = errors.New("String contains invalid UTF-8 sequences") - -type UnsupportedTypeError struct { - Type reflect.Type -} - -func (e *UnsupportedTypeError) Error() string { - return fmt.Sprintf("Unsupported type for marshaling: %s\n", e.Type.String()) -} diff --git a/forged/internal/bare/limit.go b/forged/internal/bare/limit.go deleted file mode 100644 index 212bc05..0000000 --- a/forged/internal/bare/limit.go +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Drew Devault <https://drewdevault.com> - -package bare - -import ( - "errors" - "io" -) - -var ( - maxUnmarshalBytes uint64 = 1024 * 1024 * 32 /* 32 MiB */ - maxArrayLength uint64 = 1024 * 4 /* 4096 elements */ - maxMapSize uint64 = 1024 -) - -// MaxUnmarshalBytes sets the maximum size of a message decoded by unmarshal. -// By default, this is set to 32 MiB. -func MaxUnmarshalBytes(bytes uint64) { - maxUnmarshalBytes = bytes -} - -// MaxArrayLength sets maximum number of elements in array. Defaults to 4096 elements -func MaxArrayLength(length uint64) { - maxArrayLength = length -} - -// MaxMapSize sets maximum size of map. Defaults to 1024 key/value pairs -func MaxMapSize(size uint64) { - maxMapSize = size -} - -// Use MaxUnmarshalBytes to prevent this error from occuring on messages which -// are large by design. -var ErrLimitExceeded = errors.New("Maximum message size exceeded") - -// Identical to io.LimitedReader, except it returns our custom error instead of -// EOF if the limit is reached. -type limitedReader struct { - R io.Reader - N uint64 -} - -func (l *limitedReader) Read(p []byte) (n int, err error) { - if l.N <= 0 { - return 0, ErrLimitExceeded - } - if uint64(len(p)) > l.N { - p = p[0:l.N] - } - n, err = l.R.Read(p) - l.N -= uint64(n) - return -} - -func newLimitedReader(r io.Reader) *limitedReader { - return &limitedReader{r, maxUnmarshalBytes} -} diff --git a/forged/internal/bare/marshal.go b/forged/internal/bare/marshal.go deleted file mode 100644 index 1ce942d..0000000 --- a/forged/internal/bare/marshal.go +++ /dev/null @@ -1,311 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Drew Devault <https://drewdevault.com> - -package bare - -import ( - "bytes" - "errors" - "fmt" - "reflect" - "sync" -) - -// A type which implements this interface will be responsible for marshaling -// itself when encountered. -type Marshalable interface { - Marshal(w *Writer) error -} - -var encoderBufferPool = sync.Pool{ - New: func() interface{} { - buf := &bytes.Buffer{} - buf.Grow(32) - return buf - }, -} - -// Marshals a value (val, which must be a pointer) into a BARE message. -// -// The encoding of each struct field can be customized by the format string -// stored under the "bare" key in the struct field's tag. -// -// As a special case, if the field tag is "-", the field is always omitted. -func Marshal(val interface{}) ([]byte, error) { - // reuse buffers from previous serializations - b := encoderBufferPool.Get().(*bytes.Buffer) - defer func() { - b.Reset() - encoderBufferPool.Put(b) - }() - - w := NewWriter(b) - err := MarshalWriter(w, val) - - msg := make([]byte, b.Len()) - copy(msg, b.Bytes()) - - return msg, err -} - -// Marshals a value (val, which must be a pointer) into a BARE message and -// writes it to a Writer. See Marshal for details. -func MarshalWriter(w *Writer, val interface{}) error { - t := reflect.TypeOf(val) - v := reflect.ValueOf(val) - if t.Kind() != reflect.Ptr { - return errors.New("Expected val to be pointer type") - } - - return getEncoder(t.Elem())(w, v.Elem()) -} - -type encodeFunc func(w *Writer, v reflect.Value) error - -var encodeFuncCache sync.Map // map[reflect.Type]encodeFunc - -// get decoder from cache -func getEncoder(t reflect.Type) encodeFunc { - if f, ok := encodeFuncCache.Load(t); ok { - return f.(encodeFunc) - } - - f := encoderFunc(t) - encodeFuncCache.Store(t, f) - return f -} - -var marshalableInterface = reflect.TypeOf((*Unmarshalable)(nil)).Elem() - -func encoderFunc(t reflect.Type) encodeFunc { - if reflect.PointerTo(t).Implements(marshalableInterface) { - return func(w *Writer, v reflect.Value) error { - uv := v.Addr().Interface().(Marshalable) - return uv.Marshal(w) - } - } - - if t.Kind() == reflect.Interface && t.Implements(unionInterface) { - return encodeUnion(t) - } - - switch t.Kind() { - case reflect.Ptr: - return encodeOptional(t.Elem()) - case reflect.Struct: - return encodeStruct(t) - case reflect.Array: - return encodeArray(t) - case reflect.Slice: - return encodeSlice(t) - case reflect.Map: - return encodeMap(t) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return encodeUint - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return encodeInt - case reflect.Float32, reflect.Float64: - return encodeFloat - case reflect.Bool: - return encodeBool - case reflect.String: - return encodeString - } - - return func(w *Writer, v reflect.Value) error { - return &UnsupportedTypeError{v.Type()} - } -} - -func encodeOptional(t reflect.Type) encodeFunc { - return func(w *Writer, v reflect.Value) error { - if v.IsNil() { - return w.WriteBool(false) - } - - if err := w.WriteBool(true); err != nil { - return err - } - - return getEncoder(t)(w, v.Elem()) - } -} - -func encodeStruct(t reflect.Type) encodeFunc { - n := t.NumField() - encoders := make([]encodeFunc, n) - for i := 0; i < n; i++ { - field := t.Field(i) - if field.Tag.Get("bare") == "-" { - continue - } - encoders[i] = getEncoder(field.Type) - } - - return func(w *Writer, v reflect.Value) error { - for i := 0; i < n; i++ { - if encoders[i] == nil { - continue - } - err := encoders[i](w, v.Field(i)) - if err != nil { - return err - } - } - return nil - } -} - -func encodeArray(t reflect.Type) encodeFunc { - f := getEncoder(t.Elem()) - len := t.Len() - - return func(w *Writer, v reflect.Value) error { - for i := 0; i < len; i++ { - if err := f(w, v.Index(i)); err != nil { - return err - } - } - return nil - } -} - -func encodeSlice(t reflect.Type) encodeFunc { - elem := t.Elem() - f := getEncoder(elem) - - return func(w *Writer, v reflect.Value) error { - if err := w.WriteUint(uint64(v.Len())); err != nil { - return err - } - - for i := 0; i < v.Len(); i++ { - if err := f(w, v.Index(i)); err != nil { - return err - } - } - return nil - } -} - -func encodeMap(t reflect.Type) encodeFunc { - keyType := t.Key() - keyf := getEncoder(keyType) - - valueType := t.Elem() - valf := getEncoder(valueType) - - return func(w *Writer, v reflect.Value) error { - if err := w.WriteUint(uint64(v.Len())); err != nil { - return err - } - - iter := v.MapRange() - for iter.Next() { - if err := keyf(w, iter.Key()); err != nil { - return err - } - if err := valf(w, iter.Value()); err != nil { - return err - } - } - return nil - } -} - -func encodeUnion(t reflect.Type) encodeFunc { - ut, ok := unionRegistry[t] - if !ok { - return func(w *Writer, v reflect.Value) error { - return fmt.Errorf("Union type %s is not registered", t.Name()) - } - } - - encoders := make(map[uint64]encodeFunc) - for tag, t := range ut.types { - encoders[tag] = getEncoder(t) - } - - return func(w *Writer, v reflect.Value) error { - t := v.Elem().Type() - if t.Kind() == reflect.Ptr { - // If T is a valid union value type, *T is valid too. - t = t.Elem() - v = v.Elem() - } - tag, ok := ut.tags[t] - if !ok { - return fmt.Errorf("Invalid union value: %s", v.Elem().String()) - } - - if err := w.WriteUint(tag); err != nil { - return err - } - - return encoders[tag](w, v.Elem()) - } -} - -func encodeUint(w *Writer, v reflect.Value) error { - switch getIntKind(v.Type()) { - case reflect.Uint: - return w.WriteUint(v.Uint()) - - case reflect.Uint8: - return w.WriteU8(uint8(v.Uint())) - - case reflect.Uint16: - return w.WriteU16(uint16(v.Uint())) - - case reflect.Uint32: - return w.WriteU32(uint32(v.Uint())) - - case reflect.Uint64: - return w.WriteU64(uint64(v.Uint())) - } - - panic("not uint") -} - -func encodeInt(w *Writer, v reflect.Value) error { - switch getIntKind(v.Type()) { - case reflect.Int: - return w.WriteInt(v.Int()) - - case reflect.Int8: - return w.WriteI8(int8(v.Int())) - - case reflect.Int16: - return w.WriteI16(int16(v.Int())) - - case reflect.Int32: - return w.WriteI32(int32(v.Int())) - - case reflect.Int64: - return w.WriteI64(int64(v.Int())) - } - - panic("not int") -} - -func encodeFloat(w *Writer, v reflect.Value) error { - switch v.Type().Kind() { - case reflect.Float32: - return w.WriteF32(float32(v.Float())) - case reflect.Float64: - return w.WriteF64(v.Float()) - } - - panic("not float") -} - -func encodeBool(w *Writer, v reflect.Value) error { - return w.WriteBool(v.Bool()) -} - -func encodeString(w *Writer, v reflect.Value) error { - if v.Kind() != reflect.String { - panic("not string") - } - return w.WriteString(v.String()) -} diff --git a/forged/internal/bare/reader.go b/forged/internal/bare/reader.go deleted file mode 100644 index 58325e3..0000000 --- a/forged/internal/bare/reader.go +++ /dev/null @@ -1,190 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Drew Devault <https://drewdevault.com> - -package bare - -import ( - "encoding/binary" - "fmt" - "io" - "math" - "unicode/utf8" - - "go.lindenii.runxiyu.org/forge/forged/internal/misc" -) - -type byteReader interface { - io.Reader - io.ByteReader -} - -// A Reader for BARE primitive types. -type Reader struct { - base byteReader - scratch [8]byte -} - -type simpleByteReader struct { - io.Reader - scratch [1]byte -} - -func (r simpleByteReader) ReadByte() (byte, error) { - // using reference type here saves us allocations - _, err := r.Read(r.scratch[:]) - return r.scratch[0], err -} - -// Returns a new BARE primitive reader wrapping the given io.Reader. -func NewReader(base io.Reader) *Reader { - br, ok := base.(byteReader) - if !ok { - br = simpleByteReader{Reader: base} - } - return &Reader{base: br} -} - -func (r *Reader) ReadUint() (uint64, error) { - x, err := binary.ReadUvarint(r.base) - if err != nil { - return x, err - } - return x, nil -} - -func (r *Reader) ReadU8() (uint8, error) { - return r.base.ReadByte() -} - -func (r *Reader) ReadU16() (uint16, error) { - var i uint16 - if _, err := io.ReadAtLeast(r.base, r.scratch[:2], 2); err != nil { - return i, err - } - return binary.LittleEndian.Uint16(r.scratch[:]), nil -} - -func (r *Reader) ReadU32() (uint32, error) { - var i uint32 - if _, err := io.ReadAtLeast(r.base, r.scratch[:4], 4); err != nil { - return i, err - } - return binary.LittleEndian.Uint32(r.scratch[:]), nil -} - -func (r *Reader) ReadU64() (uint64, error) { - var i uint64 - if _, err := io.ReadAtLeast(r.base, r.scratch[:8], 8); err != nil { - return i, err - } - return binary.LittleEndian.Uint64(r.scratch[:]), nil -} - -func (r *Reader) ReadInt() (int64, error) { - return binary.ReadVarint(r.base) -} - -func (r *Reader) ReadI8() (int8, error) { - b, err := r.base.ReadByte() - return int8(b), err -} - -func (r *Reader) ReadI16() (int16, error) { - var i int16 - if _, err := io.ReadAtLeast(r.base, r.scratch[:2], 2); err != nil { - return i, err - } - return int16(binary.LittleEndian.Uint16(r.scratch[:])), nil -} - -func (r *Reader) ReadI32() (int32, error) { - var i int32 - if _, err := io.ReadAtLeast(r.base, r.scratch[:4], 4); err != nil { - return i, err - } - return int32(binary.LittleEndian.Uint32(r.scratch[:])), nil -} - -func (r *Reader) ReadI64() (int64, error) { - var i int64 - if _, err := io.ReadAtLeast(r.base, r.scratch[:], 8); err != nil { - return i, err - } - return int64(binary.LittleEndian.Uint64(r.scratch[:])), nil -} - -func (r *Reader) ReadF32() (float32, error) { - u, err := r.ReadU32() - f := math.Float32frombits(u) - if math.IsNaN(float64(f)) { - return 0.0, fmt.Errorf("NaN is not permitted in BARE floats") - } - return f, err -} - -func (r *Reader) ReadF64() (float64, error) { - u, err := r.ReadU64() - f := math.Float64frombits(u) - if math.IsNaN(f) { - return 0.0, fmt.Errorf("NaN is not permitted in BARE floats") - } - return f, err -} - -func (r *Reader) ReadBool() (bool, error) { - b, err := r.ReadU8() - if err != nil { - return false, err - } - - if b > 1 { - return false, fmt.Errorf("Invalid bool value: %#x", b) - } - - return b == 1, nil -} - -func (r *Reader) ReadString() (string, error) { - buf, err := r.ReadData() - if err != nil { - return "", err - } - if !utf8.Valid(buf) { - return "", ErrInvalidStr - } - return misc.BytesToString(buf), nil -} - -// Reads a fixed amount of arbitrary data, defined by the length of the slice. -func (r *Reader) ReadDataFixed(dest []byte) error { - var amt int = 0 - for amt < len(dest) { - n, err := r.base.Read(dest[amt:]) - if err != nil { - return err - } - amt += n - } - return nil -} - -// Reads arbitrary data whose length is read from the message. -func (r *Reader) ReadData() ([]byte, error) { - l, err := r.ReadUint() - if err != nil { - return nil, err - } - if l >= maxUnmarshalBytes { - return nil, ErrLimitExceeded - } - buf := make([]byte, l) - var amt uint64 = 0 - for amt < l { - n, err := r.base.Read(buf[amt:]) - if err != nil { - return nil, err - } - amt += uint64(n) - } - return buf, nil -} diff --git a/forged/internal/bare/unions.go b/forged/internal/bare/unions.go deleted file mode 100644 index 0270a5f..0000000 --- a/forged/internal/bare/unions.go +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Drew Devault <https://drewdevault.com> - -package bare - -import ( - "fmt" - "reflect" -) - -// Any type which is a union member must implement this interface. You must -// also call RegisterUnion for go-bare to marshal or unmarshal messages which -// utilize your union type. -type Union interface { - IsUnion() -} - -type UnionTags struct { - iface reflect.Type - tags map[reflect.Type]uint64 - types map[uint64]reflect.Type -} - -var unionInterface = reflect.TypeOf((*Union)(nil)).Elem() -var unionRegistry map[reflect.Type]*UnionTags - -func init() { - unionRegistry = make(map[reflect.Type]*UnionTags) -} - -// Registers a union type in this context. Pass the union interface and the -// list of types associated with it, sorted ascending by their union tag. -func RegisterUnion(iface interface{}) *UnionTags { - ity := reflect.TypeOf(iface).Elem() - if _, ok := unionRegistry[ity]; ok { - panic(fmt.Errorf("Type %s has already been registered", ity.Name())) - } - - if !ity.Implements(reflect.TypeOf((*Union)(nil)).Elem()) { - panic(fmt.Errorf("Type %s does not implement bare.Union", ity.Name())) - } - - utypes := &UnionTags{ - iface: ity, - tags: make(map[reflect.Type]uint64), - types: make(map[uint64]reflect.Type), - } - unionRegistry[ity] = utypes - return utypes -} - -func (ut *UnionTags) Member(t interface{}, tag uint64) *UnionTags { - ty := reflect.TypeOf(t) - if !ty.AssignableTo(ut.iface) { - panic(fmt.Errorf("Type %s does not implement interface %s", - ty.Name(), ut.iface.Name())) - } - if _, ok := ut.tags[ty]; ok { - panic(fmt.Errorf("Type %s is already registered for union %s", - ty.Name(), ut.iface.Name())) - } - if _, ok := ut.types[tag]; ok { - panic(fmt.Errorf("Tag %d is already registered for union %s", - tag, ut.iface.Name())) - } - ut.tags[ty] = tag - ut.types[tag] = ty - return ut -} - -func (ut *UnionTags) TagFor(v interface{}) (uint64, bool) { - tag, ok := ut.tags[reflect.TypeOf(v)] - return tag, ok -} - -func (ut *UnionTags) TypeFor(tag uint64) (reflect.Type, bool) { - t, ok := ut.types[tag] - return t, ok -} diff --git a/forged/internal/bare/unmarshal.go b/forged/internal/bare/unmarshal.go deleted file mode 100644 index d55f32c..0000000 --- a/forged/internal/bare/unmarshal.go +++ /dev/null @@ -1,362 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Drew Devault <https://drewdevault.com> - -package bare - -import ( - "bytes" - "errors" - "fmt" - "io" - "reflect" - "sync" -) - -// A type which implements this interface will be responsible for unmarshaling -// itself when encountered. -type Unmarshalable interface { - Unmarshal(r *Reader) error -} - -// Unmarshals a BARE message into val, which must be a pointer to a value of -// the message type. -func Unmarshal(data []byte, val interface{}) error { - b := bytes.NewReader(data) - r := NewReader(b) - return UnmarshalBareReader(r, val) -} - -// Unmarshals a BARE message into value (val, which must be a pointer), from a -// reader. See Unmarshal for details. -func UnmarshalReader(r io.Reader, val interface{}) error { - r = newLimitedReader(r) - return UnmarshalBareReader(NewReader(r), val) -} - -type decodeFunc func(r *Reader, v reflect.Value) error - -var decodeFuncCache sync.Map // map[reflect.Type]decodeFunc - -func UnmarshalBareReader(r *Reader, val interface{}) error { - t := reflect.TypeOf(val) - v := reflect.ValueOf(val) - if t.Kind() != reflect.Ptr { - return errors.New("Expected val to be pointer type") - } - - return getDecoder(t.Elem())(r, v.Elem()) -} - -// get decoder from cache -func getDecoder(t reflect.Type) decodeFunc { - if f, ok := decodeFuncCache.Load(t); ok { - return f.(decodeFunc) - } - - f := decoderFunc(t) - decodeFuncCache.Store(t, f) - return f -} - -var unmarshalableInterface = reflect.TypeOf((*Unmarshalable)(nil)).Elem() - -func decoderFunc(t reflect.Type) decodeFunc { - if reflect.PointerTo(t).Implements(unmarshalableInterface) { - return func(r *Reader, v reflect.Value) error { - uv := v.Addr().Interface().(Unmarshalable) - return uv.Unmarshal(r) - } - } - - if t.Kind() == reflect.Interface && t.Implements(unionInterface) { - return decodeUnion(t) - } - - switch t.Kind() { - case reflect.Ptr: - return decodeOptional(t.Elem()) - case reflect.Struct: - return decodeStruct(t) - case reflect.Array: - return decodeArray(t) - case reflect.Slice: - return decodeSlice(t) - case reflect.Map: - return decodeMap(t) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return decodeUint - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return decodeInt - case reflect.Float32, reflect.Float64: - return decodeFloat - case reflect.Bool: - return decodeBool - case reflect.String: - return decodeString - } - - return func(r *Reader, v reflect.Value) error { - return &UnsupportedTypeError{v.Type()} - } -} - -func decodeOptional(t reflect.Type) decodeFunc { - return func(r *Reader, v reflect.Value) error { - s, err := r.ReadU8() - if err != nil { - return err - } - - if s > 1 { - return fmt.Errorf("Invalid optional value: %#x", s) - } - - if s == 0 { - return nil - } - - v.Set(reflect.New(t)) - return getDecoder(t)(r, v.Elem()) - } -} - -func decodeStruct(t reflect.Type) decodeFunc { - n := t.NumField() - decoders := make([]decodeFunc, n) - for i := 0; i < n; i++ { - field := t.Field(i) - if field.Tag.Get("bare") == "-" { - continue - } - decoders[i] = getDecoder(field.Type) - } - - return func(r *Reader, v reflect.Value) error { - for i := 0; i < n; i++ { - if decoders[i] == nil { - continue - } - err := decoders[i](r, v.Field(i)) - if err != nil { - return err - } - } - return nil - } -} - -func decodeArray(t reflect.Type) decodeFunc { - f := getDecoder(t.Elem()) - len := t.Len() - - return func(r *Reader, v reflect.Value) error { - for i := 0; i < len; i++ { - err := f(r, v.Index(i)) - if err != nil { - return err - } - } - return nil - } -} - -func decodeSlice(t reflect.Type) decodeFunc { - elem := t.Elem() - f := getDecoder(elem) - - return func(r *Reader, v reflect.Value) error { - len, err := r.ReadUint() - if err != nil { - return err - } - - if len > maxArrayLength { - return fmt.Errorf("Array length %d exceeds configured limit of %d", len, maxArrayLength) - } - - v.Set(reflect.MakeSlice(t, int(len), int(len))) - - for i := 0; i < int(len); i++ { - if err := f(r, v.Index(i)); err != nil { - return err - } - } - return nil - } -} - -func decodeMap(t reflect.Type) decodeFunc { - keyType := t.Key() - keyf := getDecoder(keyType) - - valueType := t.Elem() - valf := getDecoder(valueType) - - return func(r *Reader, v reflect.Value) error { - size, err := r.ReadUint() - if err != nil { - return err - } - - if size > maxMapSize { - return fmt.Errorf("Map size %d exceeds configured limit of %d", size, maxMapSize) - } - - v.Set(reflect.MakeMapWithSize(t, int(size))) - - key := reflect.New(keyType).Elem() - value := reflect.New(valueType).Elem() - - for i := uint64(0); i < size; i++ { - if err := keyf(r, key); err != nil { - return err - } - - if v.MapIndex(key).Kind() > reflect.Invalid { - return fmt.Errorf("Encountered duplicate map key: %v", key.Interface()) - } - - if err := valf(r, value); err != nil { - return err - } - - v.SetMapIndex(key, value) - } - return nil - } -} - -func decodeUnion(t reflect.Type) decodeFunc { - ut, ok := unionRegistry[t] - if !ok { - return func(r *Reader, v reflect.Value) error { - return fmt.Errorf("Union type %s is not registered", t.Name()) - } - } - - decoders := make(map[uint64]decodeFunc) - for tag, t := range ut.types { - t := t - f := getDecoder(t) - - decoders[tag] = func(r *Reader, v reflect.Value) error { - nv := reflect.New(t) - if err := f(r, nv.Elem()); err != nil { - return err - } - - v.Set(nv) - return nil - } - } - - return func(r *Reader, v reflect.Value) error { - tag, err := r.ReadUint() - if err != nil { - return err - } - - if f, ok := decoders[tag]; ok { - return f(r, v) - } - - return fmt.Errorf("Invalid union tag %d for type %s", tag, t.Name()) - } -} - -func decodeUint(r *Reader, v reflect.Value) error { - var err error - switch getIntKind(v.Type()) { - case reflect.Uint: - var u uint64 - u, err = r.ReadUint() - v.SetUint(u) - - case reflect.Uint8: - var u uint8 - u, err = r.ReadU8() - v.SetUint(uint64(u)) - - case reflect.Uint16: - var u uint16 - u, err = r.ReadU16() - v.SetUint(uint64(u)) - case reflect.Uint32: - var u uint32 - u, err = r.ReadU32() - v.SetUint(uint64(u)) - - case reflect.Uint64: - var u uint64 - u, err = r.ReadU64() - v.SetUint(uint64(u)) - - default: - panic("not an uint") - } - - return err -} - -func decodeInt(r *Reader, v reflect.Value) error { - var err error - switch getIntKind(v.Type()) { - case reflect.Int: - var i int64 - i, err = r.ReadInt() - v.SetInt(i) - - case reflect.Int8: - var i int8 - i, err = r.ReadI8() - v.SetInt(int64(i)) - - case reflect.Int16: - var i int16 - i, err = r.ReadI16() - v.SetInt(int64(i)) - case reflect.Int32: - var i int32 - i, err = r.ReadI32() - v.SetInt(int64(i)) - - case reflect.Int64: - var i int64 - i, err = r.ReadI64() - v.SetInt(int64(i)) - - default: - panic("not an int") - } - - return err -} - -func decodeFloat(r *Reader, v reflect.Value) error { - var err error - switch v.Type().Kind() { - case reflect.Float32: - var f float32 - f, err = r.ReadF32() - v.SetFloat(float64(f)) - case reflect.Float64: - var f float64 - f, err = r.ReadF64() - v.SetFloat(f) - default: - panic("not a float") - } - return err -} - -func decodeBool(r *Reader, v reflect.Value) error { - b, err := r.ReadBool() - v.SetBool(b) - return err -} - -func decodeString(r *Reader, v reflect.Value) error { - s, err := r.ReadString() - v.SetString(s) - return err -} diff --git a/forged/internal/bare/varint.go b/forged/internal/bare/varint.go deleted file mode 100644 index a185ac8..0000000 --- a/forged/internal/bare/varint.go +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Drew Devault <https://drewdevault.com> - -package bare - -import ( - "reflect" -) - -// Int is a variable-length encoded signed integer. -type Int int64 - -// Uint is a variable-length encoded unsigned integer. -type Uint uint64 - -var ( - intType = reflect.TypeOf(Int(0)) - uintType = reflect.TypeOf(Uint(0)) -) - -func getIntKind(t reflect.Type) reflect.Kind { - switch t { - case intType: - return reflect.Int - case uintType: - return reflect.Uint - default: - return t.Kind() - } -} diff --git a/forged/internal/bare/writer.go b/forged/internal/bare/writer.go deleted file mode 100644 index bada045..0000000 --- a/forged/internal/bare/writer.go +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2025 Drew Devault <https://drewdevault.com> - -package bare - -import ( - "encoding/binary" - "fmt" - "io" - "math" - - "go.lindenii.runxiyu.org/forge/forged/internal/misc" -) - -// A Writer for BARE primitive types. -type Writer struct { - base io.Writer - scratch [binary.MaxVarintLen64]byte -} - -// Returns a new BARE primitive writer wrapping the given io.Writer. -func NewWriter(base io.Writer) *Writer { - return &Writer{base: base} -} - -func (w *Writer) WriteUint(i uint64) error { - n := binary.PutUvarint(w.scratch[:], i) - _, err := w.base.Write(w.scratch[:n]) - return err -} - -func (w *Writer) WriteU8(i uint8) error { - return binary.Write(w.base, binary.LittleEndian, i) -} - -func (w *Writer) WriteU16(i uint16) error { - return binary.Write(w.base, binary.LittleEndian, i) -} - -func (w *Writer) WriteU32(i uint32) error { - return binary.Write(w.base, binary.LittleEndian, i) -} - -func (w *Writer) WriteU64(i uint64) error { - return binary.Write(w.base, binary.LittleEndian, i) -} - -func (w *Writer) WriteInt(i int64) error { - var buf [binary.MaxVarintLen64]byte - n := binary.PutVarint(buf[:], i) - _, err := w.base.Write(buf[:n]) - return err -} - -func (w *Writer) WriteI8(i int8) error { - return binary.Write(w.base, binary.LittleEndian, i) -} - -func (w *Writer) WriteI16(i int16) error { - return binary.Write(w.base, binary.LittleEndian, i) -} - -func (w *Writer) WriteI32(i int32) error { - return binary.Write(w.base, binary.LittleEndian, i) -} - -func (w *Writer) WriteI64(i int64) error { - return binary.Write(w.base, binary.LittleEndian, i) -} - -func (w *Writer) WriteF32(f float32) error { - if math.IsNaN(float64(f)) { - return fmt.Errorf("NaN is not permitted in BARE floats") - } - return binary.Write(w.base, binary.LittleEndian, f) -} - -func (w *Writer) WriteF64(f float64) error { - if math.IsNaN(f) { - return fmt.Errorf("NaN is not permitted in BARE floats") - } - return binary.Write(w.base, binary.LittleEndian, f) -} - -func (w *Writer) WriteBool(b bool) error { - return binary.Write(w.base, binary.LittleEndian, b) -} - -func (w *Writer) WriteString(str string) error { - return w.WriteData(misc.StringToBytes(str)) -} - -// Writes a fixed amount of arbitrary data, defined by the length of the slice. -func (w *Writer) WriteDataFixed(data []byte) error { - var amt int = 0 - for amt < len(data) { - n, err := w.base.Write(data[amt:]) - if err != nil { - return err - } - amt += n - } - return nil -} - -// Writes arbitrary data whose length is encoded into the message. -func (w *Writer) WriteData(data []byte) error { - err := w.WriteUint(uint64(len(data))) - if err != nil { - return err - } - var amt int = 0 - for amt < len(data) { - n, err := w.base.Write(data[amt:]) - if err != nil { - return err - } - amt += n - } - return nil -} |