// Code generated by canoto. DO NOT EDIT.
// versions:
// 	canoto v0.15.0
// source: base.go

package chain

import (
	"io"
	"reflect"
	"sync/atomic"

	"github.com/StephenButtolph/canoto"
)

// Ensure that unused imports do not error
var (
	_ atomic.Uint64

	_ = io.ErrUnexpectedEOF
)

const (
	canoto__Base__Timestamp__tag = "\x08" // canoto.Tag(1, canoto.Varint)
	canoto__Base__ChainID__tag   = "\x12" // canoto.Tag(2, canoto.Len)
	canoto__Base__MaxFee__tag    = "\x19" // canoto.Tag(3, canoto.I64)
)

type canotoData_Base struct {
	size uint64
}

// CanotoSpec returns the specification of this canoto message.
func (*Base) CanotoSpec(...reflect.Type) *canoto.Spec {
	var zero Base
	s := &canoto.Spec{
		Name: "Base",
		Fields: []canoto.FieldType{
			{
				FieldNumber: 1,
				Name:        "Timestamp",
				OneOf:       "",
				TypeInt:     canoto.SizeOf(zero.Timestamp),
			},
			{
				FieldNumber:    2,
				Name:           "ChainID",
				OneOf:          "",
				TypeFixedBytes: uint64(len(zero.ChainID)),
			},
			canoto.FieldTypeFromFint(
				/*type inference:*/ zero.MaxFee,
				/*FieldNumber:   */ 3,
				/*Name:          */ "MaxFee",
				/*FixedLength:   */ 0,
				/*Repeated:      */ false,
				/*OneOf:         */ "",
			),
		},
	}
	s.CalculateCanotoCache()
	return s
}

// MakeCanoto creates a new empty value.
func (*Base) MakeCanoto() *Base {
	return new(Base)
}

// UnmarshalCanoto unmarshals a Canoto-encoded byte slice into the struct.
//
// During parsing, the canoto cache is saved.
func (c *Base) UnmarshalCanoto(bytes []byte) error {
	r := canoto.Reader{
		B: bytes,
	}
	return c.UnmarshalCanotoFrom(r)
}

// UnmarshalCanotoFrom populates the struct from a canoto.Reader. Most users
// should just use UnmarshalCanoto.
//
// During parsing, the canoto cache is saved.
//
// This function enables configuration of reader options.
func (c *Base) UnmarshalCanotoFrom(r canoto.Reader) error {
	// Zero the struct before unmarshaling.
	*c = Base{}
	c.canotoData.size = uint64(len(r.B))

	var minField uint32
	for canoto.HasNext(&r) {
		field, wireType, err := canoto.ReadTag(&r)
		if err != nil {
			return err
		}
		if field < minField {
			return canoto.ErrInvalidFieldOrder
		}

		switch field {
		case 1:
			if wireType != canoto.Varint {
				return canoto.ErrUnexpectedWireType
			}

			if err := canoto.ReadInt(&r, &c.Timestamp); err != nil {
				return err
			}
			if canoto.IsZero(c.Timestamp) {
				return canoto.ErrZeroValue
			}
		case 2:
			if wireType != canoto.Len {
				return canoto.ErrUnexpectedWireType
			}

			const (
				expectedLength       = len(c.ChainID)
				expectedLengthUint64 = uint64(expectedLength)
			)
			var length uint64
			if err := canoto.ReadUint(&r, &length); err != nil {
				return err
			}
			if length != expectedLengthUint64 {
				return canoto.ErrInvalidLength
			}
			if expectedLength > len(r.B) {
				return io.ErrUnexpectedEOF
			}

			copy((&c.ChainID)[:], r.B)
			if canoto.IsZero(c.ChainID) {
				return canoto.ErrZeroValue
			}
			r.B = r.B[expectedLength:]
		case 3:
			if wireType != canoto.I64 {
				return canoto.ErrUnexpectedWireType
			}

			if err := canoto.ReadFint64(&r, &c.MaxFee); err != nil {
				return err
			}
			if canoto.IsZero(c.MaxFee) {
				return canoto.ErrZeroValue
			}
		default:
			return canoto.ErrUnknownField
		}

		minField = field + 1
	}
	return nil
}

// ValidCanoto validates that the struct can be correctly marshaled into the
// Canoto format.
//
// Specifically, ValidCanoto ensures:
// 1. All OneOfs are specified at most once.
// 2. All strings are valid utf-8.
// 3. All custom fields are ValidCanoto.
func (c *Base) ValidCanoto() bool {
	if c == nil {
		return true
	}
	return true
}

// CalculateCanotoCache populates size and OneOf caches based on the current
// values in the struct.
//
// It is not safe to call this function concurrently.
func (c *Base) CalculateCanotoCache() {
	if c == nil {
		return
	}
	var size uint64
	if !canoto.IsZero(c.Timestamp) {
		size += uint64(len(canoto__Base__Timestamp__tag)) + canoto.SizeInt(c.Timestamp)
	}
	if !canoto.IsZero(c.ChainID) {
		size += uint64(len(canoto__Base__ChainID__tag)) + canoto.SizeBytes((&c.ChainID)[:])
	}
	if !canoto.IsZero(c.MaxFee) {
		size += uint64(len(canoto__Base__MaxFee__tag)) + canoto.SizeFint64
	}
	c.canotoData.size = size
}

// CachedCanotoSize returns the previously calculated size of the Canoto
// representation from CalculateCanotoCache.
//
// If CalculateCanotoCache has not yet been called, it will return 0.
//
// If the struct has been modified since the last call to CalculateCanotoCache,
// the returned size may be incorrect.
func (c *Base) CachedCanotoSize() uint64 {
	if c == nil {
		return 0
	}
	return c.canotoData.size
}

// MarshalCanoto returns the Canoto representation of this struct.
//
// It is assumed that this struct is ValidCanoto.
//
// It is not safe to call this function concurrently.
func (c *Base) MarshalCanoto() []byte {
	c.CalculateCanotoCache()
	w := canoto.Writer{
		B: make([]byte, 0, c.CachedCanotoSize()),
	}
	w = c.MarshalCanotoInto(w)
	return w.B
}

// MarshalCanotoInto writes the struct into a canoto.Writer and returns the
// resulting canoto.Writer. Most users should just use MarshalCanoto.
//
// It is assumed that CalculateCanotoCache has been called since the last
// modification to this struct.
//
// It is assumed that this struct is ValidCanoto.
//
// It is not safe to call this function concurrently.
func (c *Base) MarshalCanotoInto(w canoto.Writer) canoto.Writer {
	if c == nil {
		return w
	}
	if !canoto.IsZero(c.Timestamp) {
		canoto.Append(&w, canoto__Base__Timestamp__tag)
		canoto.AppendInt(&w, c.Timestamp)
	}
	if !canoto.IsZero(c.ChainID) {
		canoto.Append(&w, canoto__Base__ChainID__tag)
		canoto.AppendBytes(&w, (&c.ChainID)[:])
	}
	if !canoto.IsZero(c.MaxFee) {
		canoto.Append(&w, canoto__Base__MaxFee__tag)
		canoto.AppendFint64(&w, c.MaxFee)
	}
	return w
}
