interfaceschema

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package interfaceschema parses, validates, and compiles Astarte interface definitions — the dynamic typed schemas (datastreams and properties) that devices and applications exchange data through.

The package mirrors upstream Astarte semantics (docs/DESIGN.md §2.6): ParseInterface performs a strict decode plus full structural validation of the Interface JSON, Compile turns a validated definition into the hot-path CompiledInterface (endpoint trie + object leaves), and CheckMinorUpgrade enforces the additive-only minor-version compatibility rule that Realm Management applies on interface updates.

Index

Constants

View Source
const (
	// MaxNameLength is the maximum interface name length.
	MaxNameLength = 128
	// MaxMappings is the maximum number of mappings per interface.
	MaxMappings = 1024
	// MaxEndpointDepth is the maximum number of endpoint levels.
	MaxEndpointDepth = 64
)

Structural limits, matching upstream Astarte (astarte_core).

View Source
const MaxPlaceholderValueLen = 256

MaxPlaceholderValueLen is the maximum byte length of a concrete path segment matched by a %{placeholder} (docs/DESIGN.md §2.6 hygiene rule).

Variables

View Source
var ErrIncompatibleUpgrade = errors.New("incompatible interface upgrade")

ErrIncompatibleUpgrade is wrapped by every CheckMinorUpgrade rejection, so callers can classify upgrade failures with errors.Is.

View Source
var ErrInvalid = errors.New("invalid interface")

ErrInvalid is wrapped by every ParseInterface failure, so callers can classify rejection with errors.Is regardless of the specific rule violated.

Functions

func CheckMinorUpgrade

func CheckMinorUpgrade(old, next *Interface) error

CheckMinorUpgrade enforces the Astarte minor-version compatibility rule exactly as Realm Management does on interface update (docs/DESIGN.md §2.6 versioning parity): next must keep the same name, major version, type, ownership, and aggregation; strictly increase the minor version; keep every existing mapping with identical attributes (description and doc may change, and placeholders may be renamed — they are not semantic); and only add mappings, never remove them.

Both arguments must be validated interfaces (from ParseInterface).

Types

type Aggregation

type Aggregation uint8

Aggregation states whether each mapping is sent individually (one value per publish, full endpoint path) or as one object document of last-level keys published on the common path prefix.

const (
	// AggregationIndividual sends one value per endpoint publish (default).
	AggregationIndividual Aggregation = iota + 1
	// AggregationObject sends all last-level values as a single document.
	AggregationObject
)

Aggregation values (wire strings: "individual", "object").

func ParseAggregation

func ParseAggregation(s string) (Aggregation, error)

ParseAggregation parses the wire form of an aggregation.

func (Aggregation) MarshalJSON

func (a Aggregation) MarshalJSON() ([]byte, error)

MarshalJSON encodes the wire form.

func (Aggregation) String

func (a Aggregation) String() string

String returns the wire form.

func (*Aggregation) UnmarshalJSON

func (a *Aggregation) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the wire form, rejecting unknown values.

type CompiledInterface

type CompiledInterface struct {
	// ID is the storage identifier of the interface.
	ID int64
	// Name is the reverse-domain interface name.
	Name string
	// Major and Minor are the interface version.
	Major, Minor int
	// Type discriminates datastream from properties.
	Type InterfaceType
	// Ownership states which side publishes on this interface.
	Ownership Ownership
	// Aggregation is individual or object.
	Aggregation Aggregation
	// Trie matches concrete full endpoint paths, segment-wise.
	Trie *EndpointTrie
	// ObjectLeaves maps, for object aggregation, each last-level name to its
	// mapping; nil for individual aggregation.
	ObjectLeaves map[string]*CompiledMapping
}

CompiledInterface is the hot-path form of a validated interface (docs/DESIGN.md §2.6): an endpoint trie for individual matching plus, for object aggregation, the last-level key → mapping table.

func Compile

func Compile(iface *Interface, ids EndpointIDResolver) (*CompiledInterface, error)

Compile turns a validated Interface into its hot-path form. The input must come from ParseInterface (or satisfy the same invariants); endpoint or aggregation violations surface as errors, not panics. With a nil resolver every ID is zero.

type CompiledMapping

type CompiledMapping struct {
	// EndpointID is the storage identifier of this endpoint.
	EndpointID int64
	// ValueType drives both validation and BSON/JSON decoding.
	ValueType ValueType
	// Reliability is the MQTT QoS byte (0, 1, or 2).
	Reliability byte
	// Retention states what happens to undeliverable values.
	Retention Retention
	// Expiry is the retention expiry; 0 means never.
	Expiry time.Duration
	// ExplicitTimestamp states whether publishes carry their own timestamp.
	ExplicitTimestamp bool
	// AllowUnset permits property unset via empty payload.
	AllowUnset bool
	// DBRetentionTTL is the database TTL; 0 means no_ttl.
	DBRetentionTTL time.Duration
}

CompiledMapping is the hot-path form of one endpoint mapping (docs/DESIGN.md §2.6). It is what the engine validates and persists against after a trie match.

type DatabaseRetentionPolicy

type DatabaseRetentionPolicy uint8

DatabaseRetentionPolicy states whether stored datastream values expire from the database.

const (
	// NoTTL keeps values forever (default).
	NoTTL DatabaseRetentionPolicy = iota
	// UseTTL expires values after database_retention_ttl seconds.
	UseTTL
)

DatabaseRetentionPolicy values (wire strings: "no_ttl", "use_ttl").

func ParseDatabaseRetentionPolicy

func ParseDatabaseRetentionPolicy(s string) (DatabaseRetentionPolicy, error)

ParseDatabaseRetentionPolicy parses the wire form of a database retention policy.

func (DatabaseRetentionPolicy) MarshalJSON

func (p DatabaseRetentionPolicy) MarshalJSON() ([]byte, error)

MarshalJSON encodes the wire form.

func (DatabaseRetentionPolicy) String

func (p DatabaseRetentionPolicy) String() string

String returns the wire form.

func (*DatabaseRetentionPolicy) UnmarshalJSON

func (p *DatabaseRetentionPolicy) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the wire form, rejecting unknown values.

type EndpointIDResolver

type EndpointIDResolver interface {
	// ResolveInterface returns the storage ID of the interface itself.
	ResolveInterface(name string, major int) (int64, error)
	// ResolveEndpoint returns the storage ID of one declared endpoint
	// pattern (for example "/%{sensor_id}/value").
	ResolveEndpoint(endpoint string) (int64, error)
}

EndpointIDResolver supplies the storage identifiers stamped into a CompiledInterface: the interface row ID and one ID per declared endpoint. The store layer implements it against the interfaces/endpoints tables; a nil resolver compiles with all IDs zero (pure in-memory use, tests).

type EndpointTrie

type EndpointTrie struct {
	// contains filtered or unexported fields
}

EndpointTrie matches concrete inbound paths (for example "/4/value") against declared endpoint patterns (for example "/%{sensor_id}/value"), segment by segment. Exact-literal children take priority over the (single) parametric child; placeholder values are charset- and length-checked but not semantically interpreted. Match is O(depth) and allocation-free.

func NewEndpointTrie

func NewEndpointTrie() *EndpointTrie

NewEndpointTrie returns an empty trie.

func (*EndpointTrie) Add

func (t *EndpointTrie) Add(endpoint string, m *CompiledMapping) error

Add inserts one endpoint pattern with its compiled mapping. The endpoint must be syntactically valid (same rules as ParseInterface); duplicate endpoints and sibling placeholders with different names are rejected. Cross-pattern conflict checking (ambiguous literal/parametric overlap) is ParseInterface's responsibility — the trie itself resolves such overlaps deterministically, exact match first.

func (*EndpointTrie) Match

func (t *EndpointTrie) Match(path string) (*CompiledMapping, bool)

Match resolves a concrete path to its compiled mapping. The path must be '/'-rooted with non-empty segments; parametric segments must additionally be ≤ 256 bytes and contain no '+' or '#'. Match never allocates.

type Interface

type Interface struct {
	// Name is the reverse-domain interface name (≤ 128 characters).
	Name string
	// Major is the major version; majors coexist as distinct interfaces.
	Major int
	// Minor is the minor version; bumps must be additive (CheckMinorUpgrade).
	Minor int
	// Type discriminates datastream from properties.
	Type InterfaceType
	// Ownership states which side publishes on this interface.
	Ownership Ownership
	// Aggregation is individual or object (defaults to individual).
	Aggregation Aggregation
	// Description is the optional human-readable summary.
	Description string
	// Doc is the optional long-form documentation.
	Doc string
	// Mappings are the declared endpoints (1 to 1024 entries).
	Mappings []Mapping
}

Interface is a parsed and validated Astarte interface definition. Instances produced by ParseInterface are structurally valid; hand-built instances should be validated by round-tripping through ParseInterface.

func ParseInterface

func ParseInterface(data []byte) (*Interface, error)

ParseInterface strictly decodes and validates an Astarte interface JSON document. Unknown fields, malformed values, and every structural rule violation (name syntax, versioning, endpoint syntax and uniqueness, aggregation and per-type field constraints) are rejected with an error wrapping ErrInvalid.

type InterfaceType

type InterfaceType uint8

InterfaceType discriminates datastream interfaces (time-ordered values) from properties interfaces (retained key/value state).

const (
	// Datastream is a stream of timestamped values.
	Datastream InterfaceType = iota + 1
	// Properties is retained, settable/unsettable key/value state.
	Properties
)

InterfaceType values (wire strings: "datastream", "properties").

func ParseInterfaceType

func ParseInterfaceType(s string) (InterfaceType, error)

ParseInterfaceType parses the wire form of an interface type.

func (InterfaceType) MarshalJSON

func (t InterfaceType) MarshalJSON() ([]byte, error)

MarshalJSON encodes the wire form.

func (InterfaceType) String

func (t InterfaceType) String() string

String returns the wire form.

func (*InterfaceType) UnmarshalJSON

func (t *InterfaceType) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the wire form, rejecting unknown values.

type Mapping

type Mapping struct {
	// Endpoint is the declared path pattern, e.g. "/%{sensor_id}/value".
	Endpoint string
	// Type is the value type of data published on this endpoint.
	Type ValueType
	// Reliability is the delivery guarantee (datastream only).
	Reliability Reliability
	// Retention states what happens to undeliverable values (datastream only).
	Retention Retention
	// Expiry is the retention expiry in seconds; 0 means never (datastream only).
	Expiry int64
	// DatabaseRetentionPolicy states whether stored values get a TTL
	// (datastream only).
	DatabaseRetentionPolicy DatabaseRetentionPolicy
	// DatabaseRetentionTTL is the database TTL in seconds; set if and only
	// if DatabaseRetentionPolicy is UseTTL (datastream only).
	DatabaseRetentionTTL int64
	// AllowUnset permits unsetting the property (properties only).
	AllowUnset bool
	// ExplicitTimestamp states whether publishes carry their own timestamp
	// (datastream only).
	ExplicitTimestamp bool
	// Description is the optional human-readable summary.
	Description string
	// Doc is the optional long-form documentation.
	Doc string
}

Mapping is one parsed endpoint declaration of an Interface.

type Ownership

type Ownership uint8

Ownership states which side of the platform writes an interface: the device or the server (AppEngine and triggers).

const (
	// OwnershipDevice marks device-published interfaces.
	OwnershipDevice Ownership = iota + 1
	// OwnershipServer marks server-published interfaces.
	OwnershipServer
)

Ownership values (wire strings: "device", "server").

func ParseOwnership

func ParseOwnership(s string) (Ownership, error)

ParseOwnership parses the wire form of an ownership.

func (Ownership) MarshalJSON

func (o Ownership) MarshalJSON() ([]byte, error)

MarshalJSON encodes the wire form.

func (Ownership) String

func (o Ownership) String() string

String returns the wire form.

func (*Ownership) UnmarshalJSON

func (o *Ownership) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the wire form, rejecting unknown values.

type Reliability

type Reliability uint8

Reliability is the delivery guarantee of a datastream mapping. Its numeric value equals the MQTT QoS level it maps to.

const (
	// ReliabilityUnreliable is at-most-once delivery (QoS 0, default).
	ReliabilityUnreliable Reliability = iota
	// ReliabilityGuaranteed is at-least-once delivery (QoS 1).
	ReliabilityGuaranteed
	// ReliabilityUnique is exactly-once delivery (QoS 2).
	ReliabilityUnique
)

Reliability values (wire strings: "unreliable", "guaranteed", "unique").

func ParseReliability

func ParseReliability(s string) (Reliability, error)

ParseReliability parses the wire form of a reliability.

func (Reliability) MarshalJSON

func (r Reliability) MarshalJSON() ([]byte, error)

MarshalJSON encodes the wire form.

func (Reliability) QoS

func (r Reliability) QoS() byte

QoS returns the MQTT QoS byte this reliability maps to (unreliable→0, guaranteed→1, unique→2).

func (Reliability) String

func (r Reliability) String() string

String returns the wire form.

func (*Reliability) UnmarshalJSON

func (r *Reliability) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the wire form, rejecting unknown values.

type Retention

type Retention uint8

Retention states what happens to datastream values that cannot be delivered immediately.

const (
	// RetentionDiscard drops undeliverable values (default).
	RetentionDiscard Retention = iota
	// RetentionVolatile keeps undeliverable values in memory.
	RetentionVolatile
	// RetentionStored keeps undeliverable values on disk.
	RetentionStored
)

Retention values (wire strings: "discard", "volatile", "stored").

func ParseRetention

func ParseRetention(s string) (Retention, error)

ParseRetention parses the wire form of a retention.

func (Retention) MarshalJSON

func (r Retention) MarshalJSON() ([]byte, error)

MarshalJSON encodes the wire form.

func (Retention) String

func (r Retention) String() string

String returns the wire form.

func (*Retention) UnmarshalJSON

func (r *Retention) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the wire form, rejecting unknown values.

type ValueType

type ValueType uint8

ValueType is the Astarte mapping value type: seven scalars and their seven array counterparts. It drives both payload validation and BSON/JSON decoding (docs/DESIGN.md §2.6 step 5).

const (
	// Double is an IEEE 754 binary64 number.
	Double ValueType = iota + 1
	// Integer is a signed 32-bit integer.
	Integer
	// Boolean is true or false.
	Boolean
	// LongInteger is a signed 64-bit integer.
	LongInteger
	// String is a UTF-8 string (≤ 64 KiB).
	String
	// BinaryBlob is an arbitrary byte sequence (base64 in JSON payloads).
	BinaryBlob
	// DateTime is a UTC timestamp with millisecond precision.
	DateTime
	// DoubleArray is a homogeneous array of Double.
	DoubleArray
	// IntegerArray is a homogeneous array of Integer.
	IntegerArray
	// BooleanArray is a homogeneous array of Boolean.
	BooleanArray
	// LongIntegerArray is a homogeneous array of LongInteger.
	LongIntegerArray
	// StringArray is a homogeneous array of String.
	StringArray
	// BinaryBlobArray is a homogeneous array of BinaryBlob.
	BinaryBlobArray
	// DateTimeArray is a homogeneous array of DateTime.
	DateTimeArray
)

ValueType values. Wire strings are the lowercase names ("double", "doublearray", ...).

func ParseValueType

func ParseValueType(s string) (ValueType, error)

ParseValueType parses the wire form of a value type.

func (ValueType) Elem

func (v ValueType) Elem() ValueType

Elem returns the scalar element type for array types and v itself for scalar types.

func (ValueType) IsArray

func (v ValueType) IsArray() bool

IsArray reports whether v is one of the seven array types.

func (ValueType) MarshalJSON

func (v ValueType) MarshalJSON() ([]byte, error)

MarshalJSON encodes the wire form.

func (ValueType) String

func (v ValueType) String() string

String returns the wire form.

func (*ValueType) UnmarshalJSON

func (v *ValueType) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the wire form, rejecting unknown values.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL