schema

package
v0.0.0-...-d88c8b5 Latest Latest
Warning

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

Go to latest
Published: Feb 9, 2021 License: Apache-2.0 Imports: 0 Imported by: 0

Documentation

Overview

Package schema defines a targeted schema language which allows one to represent all the schema information necessary to perform "structured" merges and diffs.

Due to the targeted nature of the data model, the schema language can fit in just a few hundred lines of go code, making it much more understandable and concise than e.g. OpenAPI.

This schema was derived by observing the API objects used by Kubernetes, and formalizing a model which allows certain operations ("apply") to be more well defined. It is currently missing one feature: one-of ("unions").

Index

Constants

View Source
const (
	Numeric = Scalar("numeric")
	String  = Scalar("string")
	Boolean = Scalar("boolean")
)
View Source
const (
	// Associative only applies to lists (see the documentation there).
	Associative = ElementRelationship("associative")
	// Atomic makes container types (lists, maps) behave
	// as scalars / leaf fields
	Atomic = ElementRelationship("atomic")
	// Separable means the items of the container type have no particular
	// relationship (default behavior for maps).
	Separable = ElementRelationship("separable")
)

Variables

View Source
var SchemaSchemaYAML = `` /* 2359-byte string literal not displayed */

SchemaSchemaYAML is a schema against which you can validate other schemas. It will validate itself. It can be unmarshalled into a Schema type.

Functions

This section is empty.

Types

type Atom

type Atom struct {
	*Scalar `yaml:"scalar,omitempty"`
	*List   `yaml:"list,omitempty"`
	*Map    `yaml:"map,omitempty"`
}

Atom represents the smallest possible pieces of the type system. Each set field in the Atom represents a possible type for the object. If none of the fields are set, any object will fail validation against the atom.

func (Atom) Equals

func (a Atom) Equals(b Atom) bool

Equals returns true iff the two Atoms are equal.

type ElementRelationship

type ElementRelationship string

ElementRelationship is an enum of the different possible relationships between the elements of container types (maps, lists).

type List

type List struct {
	// ElementType is the type of the list's elements.
	ElementType TypeRef `yaml:"elementType,omitempty"`

	// ElementRelationship states the relationship between the list's elements
	// and must have one of these values:
	// * `atomic`: the list is treated as a single entity, like a scalar.
	// * `associative`:
	//   - If the list element is a scalar, the list is treated as a set.
	//   - If the list element is a map, the list is treated as a map.
	// There is no default for this value for lists; all schemas must
	// explicitly state the element relationship for all lists.
	ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"`

	// Iff ElementRelationship is `associative`, and the element type is
	// map, then Keys must have non-zero length, and it lists the fields
	// of the element's map type which are to be used as the keys of the
	// list.
	//
	// TODO: change this to "non-atomic struct" above and make the code reflect this.
	//
	// Each key must refer to a single field name (no nesting, not JSONPath).
	Keys []string `yaml:"keys,omitempty"`
}

List represents a type which contains a zero or more elements, all of the same subtype. Lists may be either associative: each element is more or less independent and could be managed by separate entities in the system; or atomic, where the elements are heavily dependent on each other: it is not sensible to change one element without considering the ramifications on all the other elements.

func (List) Equals

func (a List) Equals(b List) bool

Equals returns true iff the two Lists are equal.

type Map

type Map struct {
	// Each struct field appears exactly once in this list. The order in
	// this list defines the canonical field ordering.
	Fields []StructField `yaml:"fields,omitempty"`

	// A Union is a grouping of fields with special rules. It may refer to
	// one or more fields in the above list. A given field from the above
	// list may be referenced in exactly 0 or 1 places in the below list.
	// One can have multiple unions in the same struct, but the fields can't
	// overlap between unions.
	Unions []Union `yaml:"unions,omitempty"`

	// ElementType is the type of the structs's unknown fields.
	ElementType TypeRef `yaml:"elementType,omitempty"`

	// ElementRelationship states the relationship between the map's items.
	// * `separable` (or unset) implies that each element is 100% independent.
	// * `atomic` implies that all elements depend on each other, and this
	//   is effectively a scalar / leaf field; it doesn't make sense for
	//   separate actors to set the elements. Example: an RGB color struct;
	//   it would never make sense to "own" only one component of the
	//   color.
	// The default behavior for maps is `separable`; it's permitted to
	// leave this unset to get the default behavior.
	ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"`
}

Map is a key-value pair. Its default semantics are the same as an associative list, but:

  • It is serialized differently: map: {"k": {"value": "v"}} list: [{"key": "k", "value": "v"}]
  • Keys must be string typed.
  • Keys can't have multiple components.

Optionally, maps may be atomic (for example, imagine representing an RGB color value--it doesn't make sense to have different actors own the R and G values).

Maps may also represent a type which is composed of a number of different fields. Each field has a name and a type.

func (Map) Equals

func (a Map) Equals(b Map) bool

Equals returns true iff the two Maps are equal.

type Scalar

type Scalar string

Scalar (AKA "primitive") represents a type which has a single value which is either numeric, string, or boolean.

TODO: split numeric into float/int? Something even more fine-grained?

type Schema

type Schema struct {
	Types []TypeDef `yaml:"types,omitempty"`
}

Schema is a list of named types.

func (Schema) Equals

func (a Schema) Equals(b Schema) bool

Equals returns true iff the two Schemas are equal.

func (Schema) FindNamedType

func (s Schema) FindNamedType(name string) (TypeDef, bool)

FindNamedType is a convenience function that returns the referenced TypeDef, if it exists, or (nil, false) if it doesn't.

func (*Schema) Resolve

func (s *Schema) Resolve(tr TypeRef) (Atom, bool)

Resolve is a convenience function which returns the atom referenced, whether it is inline or named. Returns (Atom{}, false) if the type can't be resolved.

This allows callers to not care about the difference between a (possibly inlined) reference and a definition.

type StructField

type StructField struct {
	// Name is the field name.
	Name string `yaml:"name,omitempty"`
	// Type is the field type.
	Type TypeRef `yaml:"type,omitempty"`
}

StructField pairs a field name with a field type.

func (StructField) Equals

func (a StructField) Equals(b StructField) bool

Equals returns true iff the two StructFields are equal.

type TypeDef

type TypeDef struct {
	// Top level types should be named. Every type must have a unique name.
	Name string `yaml:"name,omitempty"`

	Atom `yaml:"atom,omitempty,inline"`
}

TypeDef represents a named type in a schema.

func (TypeDef) Equals

func (a TypeDef) Equals(b TypeDef) bool

Equals returns true iff the two TypeDefs are equal.

type TypeRef

type TypeRef struct {
	// Either the name or one member of Atom should be set.
	NamedType *string `yaml:"namedType,omitempty"`
	Inlined   Atom    `yaml:",inline,omitempty"`
}

TypeRef either refers to a named type or declares an inlined type.

func (TypeRef) Equals

func (a TypeRef) Equals(b TypeRef) bool

Equals returns true iff the two TypeRefs are equal.

Note that two typerefs that have an equivalent type but where one is inlined and the other is named, are not considered equal.

type TypeSpecifier

type TypeSpecifier struct {
	Type   TypeRef `yaml:"type,omitempty"`
	Schema Schema  `yaml:"schema,omitempty"`
}

A TypeSpecifier references a particular type in a schema.

type Union

type Union struct {
	// Discriminator, if present, is the name of the field that
	// discriminates fields in the union. The mapping between the value of
	// the discriminator and the field is done by using the Fields list
	// below.
	Discriminator *string `yaml:"discriminator,omitempty"`

	// DeduceInvalidDiscriminator indicates if the discriminator
	// should be updated automatically based on the fields set. This
	// typically defaults to false since we don't want to deduce by
	// default (the behavior exists to maintain compatibility on
	// existing types and shouldn't be used for new types).
	DeduceInvalidDiscriminator bool `yaml:"deduceInvalidDiscriminator,omitempty"`

	// This is the list of fields that belong to this union. All the
	// fields present in here have to be part of the parent
	// structure. Discriminator (if oneOf has one), is NOT included in
	// this list. The value for field is how we map the name of the field
	// to actual value for discriminator.
	Fields []UnionField `yaml:"fields,omitempty"`
}

Union, or oneof, means that only one of multiple fields of a structure can be set at a time. Setting the discriminator helps clearing oher fields: - If discriminator changed to non-nil, and a new field has been added that doesn't match, an error is returned, - If discriminator hasn't changed and two fields or more are set, an error is returned, - If discriminator changed to non-nil, all other fields but the discriminated one will be cleared, - Otherwise, If only one field is left, update discriminator to that value.

func (Union) Equals

func (a Union) Equals(b Union) bool

Equals returns true iff the two Unions are equal.

type UnionField

type UnionField struct {
	// FieldName is the name of the field that is part of the union. This
	// is the serialized form of the field.
	FieldName string `yaml:"fieldName"`
	// Discriminatorvalue is the value of the discriminator to
	// select that field. If the union doesn't have a discriminator,
	// this field is ignored.
	DiscriminatorValue string `yaml:"discriminatorValue"`
}

UnionFields are mapping between the fields that are part of the union and their discriminated value. The discriminated value has to be set, and should not conflict with other discriminated value in the list.

func (UnionField) Equals

func (a UnionField) Equals(b UnionField) bool

Equals returns true iff the two UnionFields are equal.

Jump to

Keyboard shortcuts

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