Documentation
¶
Overview ¶
Package cate implements a Compact ASN.1 Tagged Encoding scheme.
Cate is a lightweight binary encoding with explicit type tags that is compatible with ASN.1 BER/DER structure. It's optimized for space efficiency while maintaining self-describing data. The package can encode and decode primitive types (integers, strings, booleans) and composite types (structs, slices).
Cate is not a general-purpose ASN.1 encoder or decoder. It can decode arbitrary ASN.1 TLVs, but value decoding support is intentionally limited to only what is necessary for encoding Go values.
Basic usage:
// Encoding
data, err := cate.Marshal(value)
if err != nil {
// handle error
}
// Decoding
var result MyType
err = cate.Unmarshal(data, &result)
if err != nil {
// handle error
}
For more control over encoding/decoding behavior, use the Options API:
// Enable implicit tagging and omit zero values data, err := cate.Marshal(value, cate.UseImplicitTags(true), cate.OmitZero(true)) // Decode with the same options err = cate.Unmarshal(data, &result, cate.UseImplicitTags(true), cate.OmitZero(true))
Custom types can implement the Marshaller and Unmarshaller interfaces to control their ASN.1 representation:
func (v MyType) MarshalCATE(enc *cate.Encoder) (cate.Value, error) {
// Custom encoding logic
}
func (v *MyType) UnmarshalCATE(dec *cate.Decoder, val cate.Value) error {
// Custom decoding logic
}
REAL ¶
The first byte of a REAL value specifies how it is encoded. Bits 7-6 indicate the encoding:
- 00 - decimal encoding
- 01 - special values
- 1x - binary encoding
The supported special values are:
- 0x40 = +∞
- 0x41 = -∞
- 0x42 = NaN
- 0x43 = -0.0
Decimal encoding is not supported. Decimal encoded values will be returned as [Raw]. For binary encoded values, the bit fields of the first byte are:
- Bit 7 - always 1 for binary encoding.
- Bit 6 - sign (0 = positive, 1 = negative).
- Bit 5-4 - exponent base (0 = base 2, 1 = base 8, 2 = base 16).
- Bit 3-2 - "scale factor", an extra base 2 exponent/multiplier with a value of 0-3.
- Bit 1-0 - exponent length (0-2 = exponent is the next 1-3 bytes, 3 = the next byte is the exponent length in bytes).
The remaining bytes (after the exponent) are the mantissa. The value is S × N × 2^F × base^E (S=sign, N=mantissa, F=scale factor, E=exponent).
When encoding, CATE only uses base 2 and does not use the scale factor.
Reference Handling ¶
**References are not currently supported for external types.**
Cate supports encoding and decoding of data structures with cyclic references. This allows for complex data structures like linked lists, trees with parent pointers, or general graph structures.
When encoding with references enabled:
- The encoder tracks each value it has seen using a map from value to reference ID.
- When a value is first encountered, it's assigned a unique reference ID and encoded normally.
- When a value is encountered again, only its reference ID is encoded.
During decoding:
- The decoder maintains a map from reference IDs to their corresponding values.
- When a reference is decoded, the decoder looks up the corresponding value.
- For forward references (references to values not yet seen), placeholder values are created and later populated when the actual value is decoded.
References are encoded using application-specific tags:
- For a reference definition: Application-specific tag with reference type number, containing a SEQUENCE of (INTEGER reference-id, actual-value).
- For a reference use: Application-specific tag with reference type number, containing just the INTEGER reference-id.
Types must implement the referenceable interface to participate in reference handling:
type referenceable interface {
refKey() TagNumber
}
The refKey method returns the tag number to use for references to this type.
Index ¶
- Constants
- func GetOption[V any](o Options, opt func(V) Options) V
- func GetParent[V any, D *Decoder | *DecoderFrom](dec D) (V, bool)
- func Marshal(value any, opts ...Options) ([]byte, error)
- func Unmarshal(data []byte, target any, opts ...Options) error
- type BigInt
- type BigReal
- type Boolean
- type Class
- type ConstructedValue
- type DateTime
- type DecodableValue
- type Decoder
- type DecoderFrom
- type EOC
- type Encoder
- type EncoderTo
- type Form
- type Integer
- type Marshaller
- type Null
- type OctetString
- type Options
- type PrimitiveValue
- type Real
- type Schema
- type Sequence
- type Set
- type Tag
- type TagNumber
- type Token
- type UTF8String
- type Unmarshaller
- type Value
Constants ¶
const ( // Universal is the universal ASN.1 tag class. Universal Class = 0x00 // Application is the application-specific ASN.1 tag class. Application Class = 0x40 // ContextSpecific is the context-specific ASN.1 tag class. ContextSpecific Class = 0x80 // Private is the private ASN.1 tag class. Private Class = 0xC0 // Primitive form indicates a single value. Primitive Form = 0x00 // Constructed form indicates a structured value containing other values. Constructed Form = 0x20 )
Variables ¶
This section is empty.
Functions ¶
func GetParent ¶
func GetParent[V any, D *Decoder | *DecoderFrom](dec D) (V, bool)
GetParent walks up the decode stack and returns the first parent/ancestor of type V.
func Marshal ¶
Marshal encodes the provided value into ASN.1 (BER/DER) encoded data. It handles encoding various Go types such as basic types, structs, and slices.
func Unmarshal ¶
Unmarshal decodes the ASN.1 (BER/DER) encoded data into the provided target value. It handles decoding into various Go types such as basic types, structs, and slices.
The data parameter should contain the complete ASN.1 TLV (Tag-Length-Value) encoding. The target parameter should be a pointer to the value to decode into. The opts parameter allows customizing the decoding behavior.
Types ¶
type BigInt ¶
BigInt represents an ASN.1 INTEGER value for arbitrary precision integers.
type BigReal ¶
BigReal represents an ASN.1 REAL value for arbitrary precision floating point numbers.
type Boolean ¶
type Boolean bool
Boolean represents an ASN.1 BOOLEAN value.
type Class ¶
type Class byte
Class represents the class part of an ASN.1 tag.
func (Class) IsApplication ¶
IsApplication returns true if the class is Application.
func (Class) IsContextSpecific ¶
IsContextSpecific returns true if the class is ContextSpecific.
func (Class) IsUniversal ¶
IsUniversal returns true if the class is Universal.
type ConstructedValue ¶
ConstructedValue represents an ASN.1 constructed value.
func (*ConstructedValue) Marshal ¶
func (v *ConstructedValue) Marshal() ([]byte, error)
Marshal returns the ASN.1 (BER/DER) encoding of this value, not including the tag or length.
func (*ConstructedValue) Tag ¶
func (v *ConstructedValue) Tag() Tag
Tag returns an ASN.1 constructed value tag.
type DateTime ¶
DateTime represents an ASN.1 DATE-TIME value.
type DecodableValue ¶
type DecodableValue interface {
Value
// Unmarshal decodes the raw ASN.1 value (without tag and length) into this
// value.
Unmarshal([]byte) error
}
DecodableValue is an ASN.1 value that supports decoding.
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder is an ASN.1 decoder that can decode ASN.1 values.
func NewDecoder ¶
NewDecoder creates a new ASN.1 decoder with the specified options.
func (*Decoder) Decode ¶
Decode decodes an ASN.1 value into the provided target. The target should be a pointer to the value to decode into.
type DecoderFrom ¶
type DecoderFrom struct {
// contains filtered or unexported fields
}
DecoderFrom is an ASN.1 decoder that reads from an input source.
func NewDecoderFrom ¶
func NewDecoderFrom(rd io.Reader, opts ...Options) *DecoderFrom
NewDecoderFrom creates a new ASN.1 decoder that reads from the provided io.Reader.
func (*DecoderFrom) Decode ¶
func (d *DecoderFrom) Decode(v any) error
Decode reads the next complete ASN.1 value from the input source and decodes it into the provided target. The target should be a pointer to the value to decode into.
func (*DecoderFrom) Done ¶
func (d *DecoderFrom) Done() error
Done checks if there are no more values to read from the input source. It should be called after Decode to ensure that the input contained exactly one complete ASN.1 value and no trailing data.
func (*DecoderFrom) From ¶
func (d *DecoderFrom) From(rd io.Reader) *DecoderFrom
From creates a new DecoderFrom that reads from the provided io.Reader. The resulting decoder uses the same options as the original.
func (*DecoderFrom) Next ¶
func (d *DecoderFrom) Next() (*Token, error)
Next reads the next ASN.1 token from the input source. The token contains the tag, length, and a reader for the value.
It returns an error if reading fails, such as when the input source is corrupted or contains invalid ASN.1 data. If the end of the input source is reached, it returns io.EOF.
func (*DecoderFrom) With ¶
func (d *DecoderFrom) With(opts ...Options) *DecoderFrom
With creates a new DecoderFrom with additional options. The returned decoder uses the same input source as the original, but with the merged options for decoding.
type EOC ¶
type EOC struct{}
EOC represents an ASN.1 End-Of-Content value, used to terminate constructed values with indefinite length.
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
Encoder is an ASN.1 encoder that can encode Go values to ASN.1 values.
func NewEncoder ¶
NewEncoder creates a new ASN.1 encoder with the specified options.
func (*Encoder) Encode ¶
Encode converts a Go value to its ASN.1 representation. Various Go types are mapped to specific ASN.1 types as defined by the package.
type EncoderTo ¶
type EncoderTo struct {
// contains filtered or unexported fields
}
EncoderTo is an ASN.1 encoder that writes to an output destination.
func NewEncoderTo ¶
NewEncoderTo creates a new ASN.1 encoder that writes to the provided io.Writer.
func (*EncoderTo) Encode ¶
Encode converts a Go value to its ASN.1 representation and writes the encoded data to the output destination.
type Form ¶
type Form byte
Form represents the form (primitive or constructed) part of an ASN.1 tag.
func (Form) IsConstructed ¶
IsConstructed returns true if the form is Constructed.
func (Form) IsPrimitive ¶
IsPrimitive returns true if the form is Primitive.
type Integer ¶
type Integer int64
Integer represents an ASN.1 INTEGER value that fits within an int64.
type Marshaller ¶
type Marshaller interface {
// MarshalCATE returns the ASN.1 representation of the value.
MarshalCATE(*Encoder) (Value, error)
}
Marshaller is the interface implemented by types that can marshal themselves into ASN.1 values.
type Null ¶
type Null struct{}
Null represents an ASN.1 NULL value.
type OctetString ¶
type OctetString []byte
OctetString represents an ASN.1 OCTET STRING, which is a sequence of bytes.
func (OctetString) Marshal ¶
func (v OctetString) Marshal() ([]byte, error)
Marshal returns the ASN.1 (BER/DER) encoding of this value, not including the tag or length.
func (OctetString) Tag ¶
func (v OctetString) Tag() Tag
Tag returns the ASN.1 tag for OctetString values.
func (*OctetString) Unmarshal ¶
func (v *OctetString) Unmarshal(b []byte) error
Unmarshal decodes the raw ASN.1 value (without tag and length) into this value.
type Options ¶
Options represents a set of configuration options for encoding or decoding.
func MatchFieldsByName ¶
MatchFieldsByName enables matching fields by name when decoding, instead of by field number. Specifically, when decoding struct values tagged with a schema, allow T to be decoded into S if, for each field F of T there is a corresponding field G of S with the same name and a compatible type.
func MergeOptions ¶
MergeOptions combines multiple Options into a single Options. Later options take precedence over earlier ones.
func OmitZero ¶
OmitZero configures whether to omit zero values when encoding. When enabled, struct fields with zero values will not be included in the encoding.
func OrderedMaps ¶
OrderedMaps enables ordering of map entries when encoding a map that has keys of a type that has a natural ordering, such as strings or numbers.
func UseImplicitTags ¶
UseImplicitTags configures whether to use implicit tagging for context-specific types. When enabled, primitive values are encoded directly with context-specific tags instead of being wrapped in a constructed value.
func UseTypeSchemas ¶
UseTypeSchemas configures whether to include type schema information in the encoding. When enabled, values are encoded with their type schema, allowing for type checking during decoding.
type PrimitiveValue ¶
PrimitiveValue represents an ASN.1 primitive value.
func (*PrimitiveValue) Marshal ¶
func (v *PrimitiveValue) Marshal() ([]byte, error)
Marshal returns the ASN.1 (BER/DER) encoding of this value, not including the tag or length.
func (*PrimitiveValue) Tag ¶
func (v *PrimitiveValue) Tag() Tag
Tag returns an ASN.1 primitive value tag.
type Real ¶
type Real float64
Real represents an ASN.1 REAL value that fits within a float64.
type Schema ¶
type Schema interface {
Marshaller
Unmarshaller
// contains filtered or unexported methods
}
Schema is the schema for a type. It is used internally to validate decoded values. It's only external use is for applications that wish to manage schema IDs externally.
type Sequence ¶
type Sequence []Value
Sequence represents an ASN.1 SEQUENCE, which is an ordered collection of values.
type Set ¶
type Set []Value
Set represents an ASN.1 SET, which is an unordered collection of values.
type Tag ¶
type Tag uint
Tag represents an ASN.1 tag, composed of class, form, and number components.
func (Tag) MayBeConstructed ¶
MayBeConstructed returns true if the tagged value may be represented in constructed form.
func (Tag) MayBePrimitive ¶
MayBePrimitive returns true if the tagged value may be represented in primitive form.
func (Tag) MayHaveIndefiniteLength ¶
MayHaveIndefiniteLength returns true if the tagged value may have an indefinite length.
type TagNumber ¶
type TagNumber uint
TagNumber represents the number part of an ASN.1 tag.
const ( EOCTag TagNumber = 0x00 BooleanTag TagNumber = 0x01 IntegerTag TagNumber = 0x02 BitStringTag TagNumber = 0x03 OctetStringTag TagNumber = 0x04 NullTag TagNumber = 0x05 ObjectIdentifierTag TagNumber = 0x06 ObjectDescriptorTag TagNumber = 0x07 ExternalTag TagNumber = 0x08 RealTag TagNumber = 0x09 EnumeratedTag TagNumber = 0x0A EmbeddedPdvTag TagNumber = 0x0B UTF8StringTag TagNumber = 0x0C RelativeOidTag TagNumber = 0x0D TimeTag TagNumber = 0x0E SequenceTag TagNumber = 0x10 SetTag TagNumber = 0x11 NumericStringTag TagNumber = 0x12 PrintableStringTag TagNumber = 0x13 TeletexStringTag TagNumber = 0x14 VideotexStringTag TagNumber = 0x15 IA5StringTag TagNumber = 0x16 UTCTimeTag TagNumber = 0x17 GeneralizedTimeTag TagNumber = 0x18 GraphicStringTag TagNumber = 0x19 VisibleStringTag TagNumber = 0x1A GeneralStringTag TagNumber = 0x1B UniversalStringTag TagNumber = 0x1C CharacterStringTag TagNumber = 0x1D BmpStringTag TagNumber = 0x1E DateTag TagNumber = 0x1F TimeOfDayTag TagNumber = 0x20 DateTimeTag TagNumber = 0x21 DurationTag TagNumber = 0x22 OidIriTag TagNumber = 0x23 RelativeOidIriTag TagNumber = 0x24 )
ASN.1 universal tag numbers
type Token ¶
type Token struct {
// contains filtered or unexported fields
}
Token represents an ASN.1 Tag-Length-Value (TLV) structure.
func (*Token) Discard ¶
Discard consumes and discards the token's contents. If the token has definite length, this reads and discards the token's value. If the token has indefinite length (constructed values), this reads and discards tokens until an end-of-content marker is reached.
func (*Token) Next ¶
Next returns the next token from a constructed value. Next panics if the token form is not constructed. Token returns (end-of-content, io.EOF) when the end of the constructed value is reached. If Value has been called, Next must not be called.
func (*Token) Read ¶
Read reads a primitive value. Read panics if the token form is not primitive. If Value has been called, Read must not be called.
func (*Token) Value ¶
Value reads the token value. If the class is universal and the value is a supported type, Value parses it and returns the appropriate Value. Sequences and sets will be parsed as their respective values. Constructed octet and UTF-8 strings will be concatenated. In any other case, Value returns a [Raw]. If Next or Read has been called, Value must not be called.
type UTF8String ¶
type UTF8String string
UTF8String represents an ASN.1 UTF8String, which is a UTF-8 encoded string.
func (UTF8String) Marshal ¶
func (v UTF8String) Marshal() ([]byte, error)
Marshal returns the ASN.1 (BER/DER) encoding of this value, not including the tag or length.
func (UTF8String) Tag ¶
func (v UTF8String) Tag() Tag
Tag returns the ASN.1 tag for UTF8String values.
func (*UTF8String) Unmarshal ¶
func (v *UTF8String) Unmarshal(b []byte) error
Unmarshal decodes the raw ASN.1 value (without tag and length) into this value.
type Unmarshaller ¶
type Unmarshaller interface {
// UnmarshalCATE sets the value from the provided ASN.1 value.
UnmarshalCATE(*Decoder, Value) error
}
Unmarshaller is the interface implemented by types that can unmarshal ASN.1 values into themselves.