Documentation
¶
Overview ¶
Package xtypes implements Dynamic Data for go-DDS (Milestone 9).
XTypes provides a runtime type system that allows distributed systems to evolve their data schemas without lock-step software updates. It is loosely aligned with the OMG DDS-XTypes 1.3 specification but simplified for idiomatic Go use.
Type System ¶
A TypeDescriptor describes the structure of a named type: its fields, their primitive kinds, and optional/required status. A TypeIdentifier is a compact, content-addressed fingerprint of a descriptor derived from its stable canonical hash.
Dynamic Data ¶
DynamicData is a schema-validated property map: values may only be set on fields declared in the associated TypeDescriptor. It serialises transparently to/from JSON.
Type Registry ¶
TypeRegistry is a thread-safe store of TypeObject values (descriptor + identifier pairs). Participants use the registry to announce their types and to resolve types received from peers.
Compatibility Checking ¶
CheckCompatibility implements the standard forward/backward type evolution rules:
- New optional fields added to the writer are invisible but harmless to an older reader (forward compatibility).
- New required fields expected by the reader but absent from the writer are incompatible (the reader would receive data it cannot interpret).
- Renamed or type-changed fields are always incompatible.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrTypeMismatch = errors.New("xtypes: type name already registered with different structure")
ErrTypeMismatch is returned by TypeRegistry.Register when a type with the same name but a different hash is already registered.
Functions ¶
This section is empty.
Types ¶
type CompatibilityResult ¶
type CompatibilityResult struct {
Compatible bool // true if reader and writer are compatible
Reason string // human-readable explanation when Compatible is false
}
CompatibilityResult describes whether a reader using one type descriptor can safely consume data produced by a writer using another.
func CheckCompatibility ¶
func CheckCompatibility(writerTD, readerTD *TypeDescriptor) CompatibilityResult
CheckCompatibility reports whether a reader using readerTD can safely consume data written by a writer using writerTD.
The rules follow standard schema-evolution conventions:
- Fields present in writer but absent in reader: always OK (forward compat).
- Fields present in reader but absent in writer: OK only if Optional in reader.
- Fields present in both: compatible only if they have the same Kind.
type DynamicData ¶
type DynamicData struct {
// contains filtered or unexported fields
}
DynamicData is a schema-validated property map. Values can only be set on fields declared in the associated TypeDescriptor.
DynamicData is NOT safe for concurrent use from multiple goroutines.
func NewDynamicData ¶
func NewDynamicData(td *TypeDescriptor) *DynamicData
NewDynamicData creates a DynamicData backed by td.
func (*DynamicData) FromJSON ¶
func (d *DynamicData) FromJSON(data []byte) error
FromJSON populates set fields from JSON. Only keys that match declared fields in the descriptor are stored; unknown keys are silently ignored (forward compatibility: old code reads new data).
func (*DynamicData) Get ¶
func (d *DynamicData) Get(name string) (any, bool)
Get returns the value for name. The second return is false if the field has not been set (even if it is declared in the descriptor).
func (*DynamicData) Set ¶
func (d *DynamicData) Set(name string, value any) error
Set sets the named field to value. Returns an error if name does not exist in the descriptor.
func (*DynamicData) ToJSON ¶
func (d *DynamicData) ToJSON() ([]byte, error)
ToJSON serialises the set fields to JSON.
func (*DynamicData) TypeDescriptor ¶
func (d *DynamicData) TypeDescriptor() *TypeDescriptor
TypeDescriptor returns the schema backing this DynamicData.
type FieldDescriptor ¶
type FieldDescriptor struct {
Name string // field name; must be unique within its parent
Kind TypeKind // primitive kind
Optional bool // if false, the field is required
Fields []FieldDescriptor // for KindStruct: nested field descriptors
Element *FieldDescriptor // for KindSeq: element type descriptor
}
FieldDescriptor describes one field within a TypeDescriptor.
type TypeDescriptor ¶
type TypeDescriptor struct {
Name string // type name; must be unique within a [TypeRegistry]
Version uint32 // schema version; 0 = unversioned
Fields []FieldDescriptor // top-level fields
}
TypeDescriptor describes a complete named schema.
type TypeIdentifier ¶
type TypeIdentifier struct {
Name string // type name
Hash [8]byte // first 8 bytes of SHA-256(canonical JSON representation)
}
TypeIdentifier is a compact, content-addressed reference to a TypeDescriptor. Two descriptors with identical structure produce the same TypeIdentifier regardless of the order in which they were created.
func Identify ¶
func Identify(td *TypeDescriptor) TypeIdentifier
Identify computes the TypeIdentifier for td. The hash is derived from a sorted, canonical JSON encoding of the descriptor so that structurally identical types hash identically.
type TypeObject ¶
type TypeObject struct {
ID TypeIdentifier
Descriptor TypeDescriptor
}
TypeObject pairs a TypeDescriptor with its content-addressed TypeIdentifier.
func NewTypeObject ¶
func NewTypeObject(td TypeDescriptor) *TypeObject
NewTypeObject builds a TypeObject from td, computing the identifier automatically.
type TypeRegistry ¶
type TypeRegistry struct {
// contains filtered or unexported fields
}
TypeRegistry is a thread-safe store for TypeObject values.
func NewTypeRegistry ¶
func NewTypeRegistry() *TypeRegistry
NewTypeRegistry creates an empty TypeRegistry.
func (*TypeRegistry) All ¶
func (r *TypeRegistry) All() []*TypeObject
All returns a snapshot of all registered TypeObjects in name-sorted order.
func (*TypeRegistry) Lookup ¶
func (r *TypeRegistry) Lookup(name string) (*TypeObject, bool)
Lookup returns the TypeObject registered under name, if any.
func (*TypeRegistry) Register ¶
func (r *TypeRegistry) Register(to *TypeObject) error
Register stores to. Returns ErrTypeMismatch if a type with the same Name but a different hash is already registered. Registering the same TypeObject twice (same name and hash) is a no-op.