type.go 6.98 KB
Newer Older
Eric Myhre's avatar
Eric Myhre committed
1
package schema
Eric Myhre's avatar
Eric Myhre committed
2

3
import (
4
	ipld "github.com/ipld/go-ipld-prime"
5 6
)

Eric Myhre's avatar
Eric Myhre committed
7
type TypeName string // = ast.TypeName
8

9 10
func (tn TypeName) String() string { return string(tn) }

11 12 13 14 15 16 17 18 19 20 21 22 23 24
// typesystem.Type is an union interface; each of the `Type*` concrete types
// in this package are one of its members.
//
// Specifically,
//
// 	TypeBool
// 	TypeString
// 	TypeBytes
// 	TypeInt
// 	TypeFloat
// 	TypeMap
// 	TypeList
// 	TypeLink
// 	TypeUnion
Eric Myhre's avatar
Eric Myhre committed
25
// 	TypeStruct
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
// 	TypeEnum
//
// are all of the kinds of Type.
//
// This is a closed union; you can switch upon the above members without
// including a default case.  The membership is closed by the unexported
// '_Type' method; you may use the BurntSushi/go-sumtype tool to check
// your switches for completeness.
//
// Many interesting properties of each Type are only defined for that specific
// type, so it's typical to use a type switch to handle each type of Type.
// (Your humble author is truly sorry for the word-mash that results from
// attempting to describe the types that describe the typesystem.Type.)
//
// For example, to inspect the kind of fields in a struct: you might
// cast a `Type` interface into `TypeStruct`, and then the `Fields()` on
// that `TypeStruct` can be inspected.  (`Fields()` isn't defined for any
// other kind of Type.)
type Type interface {
	// Unexported marker method to force the union closed.
	_Type()
47

48
	// Returns a pointer to the TypeSystem this Type is a member of.
Eric Myhre's avatar
Eric Myhre committed
49
	TypeSystem() *TypeSystem
50

51 52 53 54 55
	// Returns the string name of the Type.  This name is unique within the
	// universe this type is a member of, *unless* this type is Anonymous,
	// in which case a string describing the type will still be returned, but
	// that string will not be required to be unique.
	Name() TypeName
Eric Myhre's avatar
Eric Myhre committed
56

57
	// Returns the Kind of this Type.
58
	//
59 60 61 62 63
	// The returned value is a 1:1 association with which of the concrete
	// "schema.Type*" structs this interface can be cast to.
	//
	// Note that a schema.Kind is a different enum than ipld.ReprKind;
	// and furthermore, there's no strict relationship between them.
64
	// schema.TypedNode values can be described by *two* distinct ReprKinds:
65 66 67 68 69
	// one which describes how the Node itself will act,
	// and another which describes how the Node presents for serialization.
	// For some combinations of Type and representation strategy, one or both
	// of the ReprKinds can be determined statically; but not always:
	// it can sometimes be necessary to inspect the value quite concretely
70
	// (e.g., `schema.TypedNode{}.Representation().ReprKind()`) in order to find
71 72 73 74
	// out exactly how a node will be serialized!  This is because some types
	// can vary in representation kind based on their value (specifically,
	// kinded-representation unions have this property).
	Kind() Kind
Eric Myhre's avatar
Eric Myhre committed
75 76
}

77 78 79 80 81 82 83 84 85 86
var (
	_ Type = TypeBool{}
	_ Type = TypeString{}
	_ Type = TypeBytes{}
	_ Type = TypeInt{}
	_ Type = TypeFloat{}
	_ Type = TypeMap{}
	_ Type = TypeList{}
	_ Type = TypeLink{}
	_ Type = TypeUnion{}
Eric Myhre's avatar
Eric Myhre committed
87
	_ Type = TypeStruct{}
88 89 90
	_ Type = TypeEnum{}
)

91
type typeBase struct {
92
	name     TypeName
Eric Myhre's avatar
Eric Myhre committed
93
	universe *TypeSystem
94 95
}

Eric Myhre's avatar
Eric Myhre committed
96
type TypeBool struct {
97
	typeBase
Eric Myhre's avatar
Eric Myhre committed
98
}
99

Eric Myhre's avatar
Eric Myhre committed
100
type TypeString struct {
101
	typeBase
Eric Myhre's avatar
Eric Myhre committed
102
}
103

Eric Myhre's avatar
Eric Myhre committed
104
type TypeBytes struct {
105
	typeBase
Eric Myhre's avatar
Eric Myhre committed
106
}
107

Eric Myhre's avatar
Eric Myhre committed
108
type TypeInt struct {
109
	typeBase
Eric Myhre's avatar
Eric Myhre committed
110
}
111

Eric Myhre's avatar
Eric Myhre committed
112
type TypeFloat struct {
113
	typeBase
Eric Myhre's avatar
Eric Myhre committed
114
}
115

Eric Myhre's avatar
Eric Myhre committed
116
type TypeMap struct {
117
	typeBase
118 119 120 121
	anonymous     bool
	keyType       Type // must be ReprKind==string (e.g. Type==String|Enum).
	valueType     Type
	valueNullable bool
Eric Myhre's avatar
Eric Myhre committed
122
}
123

Eric Myhre's avatar
Eric Myhre committed
124
type TypeList struct {
125
	typeBase
126 127 128
	anonymous     bool
	valueType     Type
	valueNullable bool
Eric Myhre's avatar
Eric Myhre committed
129
}
130

Eric Myhre's avatar
Eric Myhre committed
131
type TypeLink struct {
132
	typeBase
133 134
	referencedType    Type
	hasReferencedType bool
Eric Myhre's avatar
Eric Myhre committed
135 136 137 138
	// ...?
}

type TypeUnion struct {
139
	typeBase
140 141 142 143 144 145 146
	// Members are listed in the order they appear in the schema.
	// To find the discriminant info, you must look inside the representation; they all contain a 'table' of some kind in which the member types are the values.
	// Note that multiple appearances of the same type as distinct members of the union is not possible.
	//  While we could do this... A: that's... odd, and nearly never called for; B: not possible with kinded mode; C: imagine the golang-native type switch!  it's impossible.
	//  We rely on this clarity in many ways: most visibly, the type-level Node implementation for a union always uses the type names as if they were map keys!  This behavior is consistent for all union representations.
	members        []Type
	representation UnionRepresentation
Eric Myhre's avatar
Eric Myhre committed
147
}
148

149
type UnionRepresentation interface{ _UnionRepresentation() }
Eric Myhre's avatar
Eric Myhre committed
150

151 152 153 154 155
func (UnionRepresentation_Keyed) _UnionRepresentation()    {}
func (UnionRepresentation_Kinded) _UnionRepresentation()   {}
func (UnionRepresentation_Envelope) _UnionRepresentation() {}
func (UnionRepresentation_Inline) _UnionRepresentation()   {}

156 157 158 159 160
// A bunch of these tables in union representation might be easier to use if flipped;
//  we almost always index into them by type (since that's what we have an ordered list of);
//  and they're unique in both directions, so it's equally valid either way.
//  The order they're currently written in matches the serial form in the schema AST.

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
type UnionRepresentation_Keyed struct {
	table map[string]Type // key is user-defined freetext
}
type UnionRepresentation_Kinded struct {
	table map[ipld.ReprKind]Type
}
type UnionRepresentation_Envelope struct {
	discriminantKey string
	contentKey      string
	table           map[string]Type // key is user-defined freetext
}
type UnionRepresentation_Inline struct {
	discriminantKey string
	table           map[string]Type // key is user-defined freetext
}
Eric Myhre's avatar
Eric Myhre committed
176

Eric Myhre's avatar
Eric Myhre committed
177
type TypeStruct struct {
178
	typeBase
179 180 181 182
	// n.b. `Fields` is an (order-preserving!) map in the schema-schema;
	//  but it's a list here, with the keys denormalized into the value,
	//   because that's typically how we use it.
	fields         []StructField
183
	fieldsMap      map[string]StructField // same content, indexed for lookup.
184
	representation StructRepresentation
Eric Myhre's avatar
Eric Myhre committed
185
}
Eric Myhre's avatar
Eric Myhre committed
186
type StructField struct {
187
	parent   *TypeStruct
188 189 190 191
	name     string
	typ      Type
	optional bool
	nullable bool
Eric Myhre's avatar
Eric Myhre committed
192 193
}

194 195 196 197 198
type StructRepresentation interface{ _StructRepresentation() }

func (StructRepresentation_Map) _StructRepresentation()         {}
func (StructRepresentation_Tuple) _StructRepresentation()       {}
func (StructRepresentation_StringPairs) _StructRepresentation() {}
199
func (StructRepresentation_Stringjoin) _StructRepresentation()  {}
200 201 202

type StructRepresentation_Map struct {
	renames   map[string]string
203
	implicits map[string]ImplicitValue
204 205 206
}
type StructRepresentation_Tuple struct{}
type StructRepresentation_StringPairs struct{ sep1, sep2 string }
207
type StructRepresentation_Stringjoin struct{ sep string }
208

Eric Myhre's avatar
Eric Myhre committed
209
type TypeEnum struct {
210
	typeBase
211
	members []string
Eric Myhre's avatar
Eric Myhre committed
212
}
213 214 215 216 217 218 219 220 221 222 223

// ImplicitValue is an sum type holding values that are implicits.
// It's not an 'Any' value because it can't be recursive
// (or to be slightly more specific, it can be one of the recursive kinds,
// but if so, only its empty value is valid here).
type ImplicitValue interface{ _ImplicitValue() }

type ImplicitValue_EmptyList struct{}
type ImplicitValue_EmptyMap struct{}
type ImplicitValue_String struct{ x string }
type ImplicitValue_Int struct{ x int }