github.com/ipld/go-ipld-prime@v0.21.0/schema/typeMethods.go (about) 1 package schema 2 3 import ( 4 "github.com/ipld/go-ipld-prime/datamodel" 5 ) 6 7 /* cookie-cutter standard interface stuff */ 8 9 func (t *typeBase) _Type(ts *TypeSystem) { 10 t.universe = ts 11 } 12 func (t typeBase) TypeSystem() *TypeSystem { return t.universe } 13 func (t typeBase) Name() TypeName { return t.name } 14 15 func (TypeBool) TypeKind() TypeKind { return TypeKind_Bool } 16 func (TypeString) TypeKind() TypeKind { return TypeKind_String } 17 func (TypeBytes) TypeKind() TypeKind { return TypeKind_Bytes } 18 func (TypeInt) TypeKind() TypeKind { return TypeKind_Int } 19 func (TypeFloat) TypeKind() TypeKind { return TypeKind_Float } 20 func (TypeAny) TypeKind() TypeKind { return TypeKind_Any } 21 func (TypeMap) TypeKind() TypeKind { return TypeKind_Map } 22 func (TypeList) TypeKind() TypeKind { return TypeKind_List } 23 func (TypeLink) TypeKind() TypeKind { return TypeKind_Link } 24 func (TypeUnion) TypeKind() TypeKind { return TypeKind_Union } 25 func (TypeStruct) TypeKind() TypeKind { return TypeKind_Struct } 26 func (TypeEnum) TypeKind() TypeKind { return TypeKind_Enum } 27 28 func (TypeBool) RepresentationBehavior() datamodel.Kind { return datamodel.Kind_Bool } 29 func (TypeString) RepresentationBehavior() datamodel.Kind { return datamodel.Kind_String } 30 func (TypeBytes) RepresentationBehavior() datamodel.Kind { return datamodel.Kind_Bytes } 31 func (TypeInt) RepresentationBehavior() datamodel.Kind { return datamodel.Kind_Int } 32 func (TypeFloat) RepresentationBehavior() datamodel.Kind { return datamodel.Kind_Float } 33 func (TypeMap) RepresentationBehavior() datamodel.Kind { return datamodel.Kind_Map } 34 func (TypeList) RepresentationBehavior() datamodel.Kind { return datamodel.Kind_List } 35 func (TypeLink) RepresentationBehavior() datamodel.Kind { return datamodel.Kind_Link } 36 func (t TypeUnion) RepresentationBehavior() datamodel.Kind { 37 switch t.representation.(type) { 38 case UnionRepresentation_Keyed: 39 return datamodel.Kind_Map 40 case UnionRepresentation_Kinded: 41 return datamodel.Kind_Invalid // you can't know with this one, until you see the value (and thus can its inhabitant's behavior)! 42 case UnionRepresentation_Envelope: 43 return datamodel.Kind_Map 44 case UnionRepresentation_Inline: 45 return datamodel.Kind_Map 46 case UnionRepresentation_Stringprefix: 47 return datamodel.Kind_String 48 default: 49 panic("unreachable") 50 } 51 } 52 func (t TypeStruct) RepresentationBehavior() datamodel.Kind { 53 switch t.representation.(type) { 54 case StructRepresentation_Map: 55 return datamodel.Kind_Map 56 case StructRepresentation_Tuple: 57 return datamodel.Kind_List 58 case StructRepresentation_ListPairs: 59 return datamodel.Kind_List 60 case StructRepresentation_StringPairs: 61 return datamodel.Kind_String 62 case StructRepresentation_Stringjoin: 63 return datamodel.Kind_String 64 default: 65 panic("unreachable") 66 } 67 } 68 func (t TypeEnum) RepresentationBehavior() datamodel.Kind { 69 // TODO: this should have a representation strategy switch too; sometimes that will indicate int representation behavior. 70 return datamodel.Kind_String 71 } 72 func (t TypeAny) RepresentationBehavior() datamodel.Kind { 73 return datamodel.Kind_Invalid // TODO: what can we possibly do here? 74 } 75 76 /* interesting methods per Type type */ 77 78 // beware: many of these methods will change when we successfully bootstrap self-hosting. 79 // 80 // The current methods return reified Type objects; in the future, there might be less of that. 81 // Returning reified Type objects requires bouncing lookups through the typesystem map; 82 // this is unavoidable because we need to handle cycles in definitions. 83 // However, the extra (and cyclic) pointers that requires won't necessarily jive well if 84 // we remake the Type types to have close resemblances to the Data Model tree data.) 85 // 86 // It's also unfortunate that some of the current methods collide in name with 87 // the names of the Data Model fields. We might reshuffling things to reduce this. 88 // 89 // At any rate, all of these changes will come as a sweep once we 90 // get a self-hosting gen of the schema-schema, not before 91 // (the effort of updating template references is substantial). 92 93 // IsAnonymous is returns true if the type was unnamed. Unnamed types will 94 // claim to have a Name property like `{Foo:Bar}`, and this is not guaranteed 95 // to be a unique string for all types in the universe. 96 func (t TypeMap) IsAnonymous() bool { 97 return t.anonymous 98 } 99 100 // KeyType returns the Type of the map keys. 101 // 102 // Note that map keys will must always be some type which is representable as a 103 // string in the IPLD Data Model (e.g. either TypeString or TypeEnum). 104 func (t TypeMap) KeyType() Type { 105 return t.universe.namedTypes[t.keyType] 106 } 107 108 // ValueType returns the Type of the map values. 109 func (t TypeMap) ValueType() Type { 110 return t.universe.namedTypes[t.valueType] 111 } 112 113 // ValueIsNullable returns a bool describing if the map values are permitted 114 // to be null. 115 func (t TypeMap) ValueIsNullable() bool { 116 return t.valueNullable 117 } 118 119 // IsAnonymous is returns true if the type was unnamed. Unnamed types will 120 // claim to have a Name property like `[Foo]`, and this is not guaranteed 121 // to be a unique string for all types in the universe. 122 func (t TypeList) IsAnonymous() bool { 123 return t.anonymous 124 } 125 126 // ValueType returns to the Type of the list values. 127 func (t TypeList) ValueType() Type { 128 return t.universe.namedTypes[t.valueType] 129 } 130 131 // ValueIsNullable returns a bool describing if the list values are permitted 132 // to be null. 133 func (t TypeList) ValueIsNullable() bool { 134 return t.valueNullable 135 } 136 137 // Members returns the list of all types that are possible inhabitants of this union. 138 func (t TypeUnion) Members() []Type { 139 a := make([]Type, len(t.members)) 140 for i := range t.members { 141 a[i] = t.universe.namedTypes[t.members[i]] 142 } 143 return a 144 } 145 146 func (t TypeUnion) RepresentationStrategy() UnionRepresentation { 147 return t.representation 148 } 149 150 func (r UnionRepresentation_Keyed) GetDiscriminant(t Type) string { 151 for d, t2 := range r.table { 152 if t2 == t.Name() { 153 return d 154 } 155 } 156 panic("that type isn't a member of this union") 157 } 158 159 func (r UnionRepresentation_Stringprefix) GetDelim() string { 160 return r.delim 161 } 162 163 func (r UnionRepresentation_Stringprefix) GetDiscriminant(t Type) string { 164 for d, t2 := range r.table { 165 if t2 == t.Name() { 166 return d 167 } 168 } 169 panic("that type isn't a member of this union") 170 } 171 172 // GetMember returns type info for the member matching the kind argument, 173 // or may return nil if that kind is not mapped to a member of this union. 174 func (r UnionRepresentation_Kinded) GetMember(k datamodel.Kind) TypeName { 175 return r.table[k] 176 } 177 178 // Fields returns a slice of descriptions of the object's fields. 179 func (t TypeStruct) Fields() []StructField { 180 return t.fields 181 } 182 183 // Field looks up a StructField by name, or returns nil if no such field. 184 func (t TypeStruct) Field(name string) *StructField { 185 if v, ok := t.fieldsMap[name]; ok { 186 return &v 187 } 188 return nil 189 } 190 191 // Parent returns the type information that this field describes a part of. 192 // 193 // While in many cases, you may know the parent already from context, 194 // there may still be situations where want to pass around a field and 195 // not need to continue passing down the parent type with it; this method 196 // helps your code be less redundant in such a situation. 197 // (You'll find this useful for looking up any rename directives, for example, 198 // when holding onto a field, since that requires looking up information from 199 // the representation strategy, which is a property of the type as a whole.) 200 func (f StructField) Parent() *TypeStruct { return f.parent } 201 202 // Name returns the string name of this field. The name is the string that 203 // will be used as a map key if the structure this field is a member of is 204 // serialized as a map representation. 205 func (f StructField) Name() string { return f.name } 206 207 // Type returns the Type of this field's value. Note the field may 208 // also be unset if it is either Optional or Nullable. 209 func (f StructField) Type() Type { return f.parent.universe.namedTypes[f.typ] } 210 211 // IsOptional returns true if the field is allowed to be absent from the object. 212 // If IsOptional is false, the field may be absent from the serial representation 213 // of the object entirely. 214 // 215 // Note being optional is different than saying the value is permitted to be null! 216 // A field may be both nullable and optional simultaneously, or either, or neither. 217 func (f StructField) IsOptional() bool { return f.optional } 218 219 // IsNullable returns true if the field value is allowed to be null. 220 // 221 // If is Nullable is false, note that it's still possible that the field value 222 // will be absent if the field is Optional! Being nullable is unrelated to 223 // whether the field's presence is optional as a whole. 224 // 225 // Note that a field may be both nullable and optional simultaneously, 226 // or either, or neither. 227 func (f StructField) IsNullable() bool { return f.nullable } 228 229 // IsMaybe returns true if the field value is allowed to be either null or absent. 230 // 231 // This is a simple "or" of the two properties, 232 // but this method is a shorthand that turns out useful often. 233 func (f StructField) IsMaybe() bool { return f.nullable || f.optional } 234 235 func (t TypeStruct) RepresentationStrategy() StructRepresentation { 236 return t.representation 237 } 238 239 func (r StructRepresentation_Map) GetFieldKey(field StructField) string { 240 if n, ok := r.renames[field.name]; ok { 241 return n 242 } 243 return field.name 244 } 245 246 func (r StructRepresentation_Map) FieldHasRename(field StructField) bool { 247 _, ok := r.renames[field.name] 248 return ok 249 } 250 251 // FieldImplicit returns the 'implicit' value for a field, or nil, if there isn't one. 252 // 253 // Because this returns the golang ImplicitValue type, which is an interface, 254 // golang type switching is needed to distinguish what it holds. 255 // (In other words, be warned that this function is not very friendly to use from templating engines.) 256 func (r StructRepresentation_Map) FieldImplicit(field StructField) ImplicitValue { 257 if r.implicits == nil { 258 return nil 259 } 260 return r.implicits[field.name] 261 } 262 263 func (r StructRepresentation_Stringjoin) GetDelim() string { 264 return r.sep 265 } 266 267 // Members returns a slice the strings which are valid inhabitants of this enum. 268 func (t TypeEnum) Members() []string { 269 return t.members 270 } 271 272 func (t TypeEnum) RepresentationStrategy() EnumRepresentation { 273 return t.representation 274 } 275 276 // Links can keep a referenced type, which is a hint only about the data on the 277 // other side of the link, no something that can be explicitly validated without 278 // loading the link 279 280 // HasReferencedType returns true if the link has a hint about the type it references 281 // false if it's generic 282 func (t TypeLink) HasReferencedType() bool { 283 return t.hasReferencedType 284 } 285 286 // ReferencedType returns the type hint for the node on the other side of the link 287 func (t TypeLink) ReferencedType() Type { 288 return t.universe.namedTypes[t.referencedType] 289 }