github.com/ipld/go-ipld-prime@v0.21.0/schema/dmt/schema.go (about) 1 package schemadmt 2 3 import ( 4 "fmt" 5 6 "github.com/ipld/go-ipld-prime/datamodel" 7 "github.com/ipld/go-ipld-prime/node/bindnode" 8 "github.com/ipld/go-ipld-prime/schema" 9 ) 10 11 // Prototypes contains some schema.TypedPrototype values which match 12 // the IPLD schema-schema -- that is, the schema that describes IPLD schemas. 13 // These prototypes create an in-memory representation that is backed by 14 // structs in this package and bindnode. 15 var Prototypes struct { 16 Schema schema.TypedPrototype 17 } 18 19 //go:generate go run -tags=schemadmtgen gen.go 20 21 // TypeSystem is a compiled equivalent of the IPLD schema-schema -- that is, the schema that describes IPLD schemas. 22 // 23 // The IPLD schema-schema can be found at https://ipld.io/specs/schemas/schema-schema.ipldsch . 24 var TypeSystem schema.TypeSystem 25 26 // In this init function, we manually create a type system that *matches* the IPLD schema-schema. 27 // This manual work is unfortunate, and also must be kept in-sync manually, 28 // but is important because breaks a cyclic dependency -- 29 // we use the compiled schema-schema produced by this to parse other schema documents. 30 // We would also use it to parse... the IPLD schema-schema... if that weren't a cyclic dependency. 31 func init() { 32 var ts schema.TypeSystem 33 ts.Init() 34 35 // I've elided all references to Advancedlayouts stuff for the moment. 36 // (Not because it's particularly hard or problematic; I just want to draw a slightly smaller circle first.) 37 38 // Prelude 39 ts.Accumulate(schema.SpawnString("String")) 40 ts.Accumulate(schema.SpawnBool("Bool")) 41 ts.Accumulate(schema.SpawnInt("Int")) 42 ts.Accumulate(schema.SpawnFloat("Float")) 43 ts.Accumulate(schema.SpawnBytes("Bytes")) 44 45 // Schema-schema! 46 // In the same order as the spec's ipldsch file. 47 // Note that ADL stuff is excluded for now, as per above. 48 ts.Accumulate(schema.SpawnString("TypeName")) 49 ts.Accumulate(schema.SpawnStruct("Schema", 50 []schema.StructField{ 51 schema.SpawnStructField("types", "Map__TypeName__TypeDefn", false, false), 52 // also: `advanced AdvancedDataLayoutMap`, but as commented above, we'll pursue this later. 53 }, 54 schema.StructRepresentation_Map{}, 55 )) 56 ts.Accumulate(schema.SpawnMap("Map__TypeName__TypeDefn", 57 "TypeName", "TypeDefn", false, 58 )) 59 ts.Accumulate(schema.SpawnUnion("TypeDefn", 60 []schema.TypeName{ 61 "TypeDefnBool", 62 "TypeDefnString", 63 "TypeDefnBytes", 64 "TypeDefnInt", 65 "TypeDefnFloat", 66 "TypeDefnMap", 67 "TypeDefnList", 68 "TypeDefnLink", 69 "TypeDefnUnion", 70 "TypeDefnStruct", 71 "TypeDefnEnum", 72 "TypeDefnUnit", 73 "TypeDefnAny", 74 "TypeDefnCopy", 75 }, 76 // TODO: spec uses inline repr. 77 schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{ 78 "bool": "TypeDefnBool", 79 "string": "TypeDefnString", 80 "bytes": "TypeDefnBytes", 81 "int": "TypeDefnInt", 82 "float": "TypeDefnFloat", 83 "map": "TypeDefnMap", 84 "list": "TypeDefnList", 85 "link": "TypeDefnLink", 86 "union": "TypeDefnUnion", 87 "struct": "TypeDefnStruct", 88 "enum": "TypeDefnEnum", 89 "unit": "TypeDefnUnit", 90 "any": "TypeDefnAny", 91 "copy": "TypeDefnCopy", 92 }), 93 )) 94 ts.Accumulate(schema.SpawnUnion("TypeNameOrInlineDefn", 95 []schema.TypeName{ 96 "TypeName", 97 "InlineDefn", 98 }, 99 schema.SpawnUnionRepresentationKinded(map[datamodel.Kind]schema.TypeName{ 100 datamodel.Kind_String: "TypeName", 101 datamodel.Kind_Map: "InlineDefn", 102 }), 103 )) 104 ts.Accumulate(schema.SpawnUnion("InlineDefn", 105 []schema.TypeName{ 106 "TypeDefnMap", 107 "TypeDefnList", 108 "TypeDefnLink", 109 }, 110 schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{ 111 "map": "TypeDefnMap", 112 "list": "TypeDefnList", 113 "link": "TypeDefnLink", 114 }), 115 )) 116 ts.Accumulate(schema.SpawnStruct("TypeDefnBool", 117 []schema.StructField{}, 118 schema.StructRepresentation_Map{}, 119 )) 120 ts.Accumulate(schema.SpawnStruct("TypeDefnString", 121 []schema.StructField{}, 122 schema.StructRepresentation_Map{}, 123 )) 124 ts.Accumulate(schema.SpawnStruct("TypeDefnBytes", 125 []schema.StructField{}, 126 // No BytesRepresentation, since we omit ADL stuff. 127 schema.StructRepresentation_Map{}, 128 )) 129 ts.Accumulate(schema.SpawnStruct("TypeDefnInt", 130 []schema.StructField{}, 131 schema.StructRepresentation_Map{}, 132 )) 133 ts.Accumulate(schema.SpawnStruct("TypeDefnFloat", 134 []schema.StructField{}, 135 schema.StructRepresentation_Map{}, 136 )) 137 ts.Accumulate(schema.SpawnStruct("TypeDefnMap", 138 []schema.StructField{ 139 schema.SpawnStructField("keyType", "TypeName", false, false), 140 schema.SpawnStructField("valueType", "TypeNameOrInlineDefn", false, false), 141 schema.SpawnStructField("valueNullable", "Bool", true, false), // TODO: wants to use the "implicit" feature, but not supported yet 142 schema.SpawnStructField("representation", "MapRepresentation", true, false), // XXXXXX 143 }, 144 schema.StructRepresentation_Map{}, 145 )) 146 ts.Accumulate(schema.SpawnUnion("MapRepresentation", 147 []schema.TypeName{ 148 "MapRepresentation_Map", 149 "MapRepresentation_Stringpairs", 150 "MapRepresentation_Listpairs", 151 }, 152 schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{ 153 "map": "MapRepresentation_Map", 154 "stringpairs": "MapRepresentation_Stringpairs", 155 "listpairs": "MapRepresentation_Listpairs", 156 }), 157 )) 158 ts.Accumulate(schema.SpawnStruct("MapRepresentation_Map", 159 []schema.StructField{}, 160 schema.StructRepresentation_Map{}, 161 )) 162 ts.Accumulate(schema.SpawnStruct("MapRepresentation_Stringpairs", 163 []schema.StructField{ 164 schema.SpawnStructField("innerDelim", "String", false, false), 165 schema.SpawnStructField("entryDelim", "String", false, false), 166 }, 167 schema.StructRepresentation_Map{}, 168 )) 169 ts.Accumulate(schema.SpawnStruct("MapRepresentation_Listpairs", 170 []schema.StructField{}, 171 schema.StructRepresentation_Map{}, 172 )) 173 ts.Accumulate(schema.SpawnStruct("TypeDefnList", 174 []schema.StructField{ 175 schema.SpawnStructField("valueType", "TypeNameOrInlineDefn", false, false), 176 schema.SpawnStructField("valueNullable", "Bool", true, false), // TODO: wants to use the "implicit" feature, but not supported yet 177 schema.SpawnStructField("representation", "ListRepresentation", true, false), // XXXXXX 178 }, 179 schema.StructRepresentation_Map{}, 180 )) 181 ts.Accumulate(schema.SpawnUnion("ListRepresentation", 182 []schema.TypeName{ 183 "ListRepresentation_List", 184 }, 185 schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{ 186 "list": "ListRepresentation_List", 187 }), 188 )) 189 ts.Accumulate(schema.SpawnStruct("ListRepresentation_List", 190 []schema.StructField{}, 191 schema.StructRepresentation_Map{}, 192 )) 193 ts.Accumulate(schema.SpawnStruct("TypeDefnUnion", 194 []schema.StructField{ 195 // n.b. we could conceivably allow TypeNameOrInlineDefn here rather than just TypeName. but... we'd rather not: imagine what that means about the type-level behavior of the union: the name munge for the anonymous type would suddenly become load-bearing. would rather not. 196 schema.SpawnStructField("members", "List__UnionMember", false, false), 197 schema.SpawnStructField("representation", "UnionRepresentation", false, false), 198 }, 199 schema.StructRepresentation_Map{}, 200 )) 201 ts.Accumulate(schema.SpawnList("List__UnionMember", 202 "UnionMember", false, 203 )) 204 ts.Accumulate(schema.SpawnUnion("UnionMember", 205 []schema.TypeName{ 206 "TypeName", 207 "UnionMemberInlineDefn", 208 }, 209 schema.SpawnUnionRepresentationKinded(map[datamodel.Kind]schema.TypeName{ 210 datamodel.Kind_String: "TypeName", 211 datamodel.Kind_Map: "UnionMemberInlineDefn", 212 }), 213 )) 214 ts.Accumulate(schema.SpawnUnion("UnionMemberInlineDefn", 215 []schema.TypeName{ 216 "TypeDefnLink", 217 }, 218 schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{ 219 "link": "TypeDefnLink", 220 }), 221 )) 222 ts.Accumulate(schema.SpawnList("List__TypeName", // todo: this is a slight hack: should be an anon inside TypeDefnUnion.members. 223 "TypeName", false, 224 )) 225 ts.Accumulate(schema.SpawnStruct("TypeDefnLink", 226 []schema.StructField{ 227 schema.SpawnStructField("expectedType", "TypeName", true, false), // todo: this uses an implicit with a value of 'any' in the schema-schema, but that's been questioned before. maybe it should simply be an optional. 228 }, 229 schema.StructRepresentation_Map{}, 230 )) 231 ts.Accumulate(schema.SpawnUnion("UnionRepresentation", 232 []schema.TypeName{ 233 "UnionRepresentation_Kinded", 234 "UnionRepresentation_Keyed", 235 "UnionRepresentation_Envelope", 236 "UnionRepresentation_Inline", 237 "UnionRepresentation_StringPrefix", 238 "UnionRepresentation_BytesPrefix", 239 }, 240 schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{ 241 "kinded": "UnionRepresentation_Kinded", 242 "keyed": "UnionRepresentation_Keyed", 243 "envelope": "UnionRepresentation_Envelope", 244 "inline": "UnionRepresentation_Inline", 245 "stringprefix": "UnionRepresentation_StringPrefix", 246 "byteprefix": "UnionRepresentation_BytesPrefix", 247 }), 248 )) 249 ts.Accumulate(schema.SpawnMap("UnionRepresentation_Kinded", 250 "RepresentationKind", "UnionMember", false, 251 )) 252 ts.Accumulate(schema.SpawnMap("UnionRepresentation_Keyed", 253 "String", "UnionMember", false, 254 )) 255 ts.Accumulate(schema.SpawnMap("Map__String__UnionMember", 256 "TypeName", "TypeDefn", false, 257 )) 258 ts.Accumulate(schema.SpawnStruct("UnionRepresentation_Envelope", 259 []schema.StructField{ 260 schema.SpawnStructField("discriminantKey", "String", false, false), 261 schema.SpawnStructField("contentKey", "String", false, false), 262 schema.SpawnStructField("discriminantTable", "Map__String__UnionMember", false, false), 263 }, 264 schema.StructRepresentation_Map{}, 265 )) 266 ts.Accumulate(schema.SpawnStruct("UnionRepresentation_Inline", 267 []schema.StructField{ 268 schema.SpawnStructField("discriminantKey", "String", false, false), 269 schema.SpawnStructField("discriminantTable", "Map__String__TypeName", false, false), 270 }, 271 schema.StructRepresentation_Map{}, 272 )) 273 ts.Accumulate(schema.SpawnStruct("UnionRepresentation_StringPrefix", 274 []schema.StructField{ 275 schema.SpawnStructField("prefixes", "Map__String__TypeName", false, false), 276 }, 277 schema.StructRepresentation_Map{}, 278 )) 279 ts.Accumulate(schema.SpawnStruct("UnionRepresentation_BytesPrefix", 280 []schema.StructField{ 281 schema.SpawnStructField("prefixes", "Map__HexString__TypeName", false, false), 282 }, 283 schema.StructRepresentation_Map{}, 284 )) 285 ts.Accumulate(schema.SpawnMap("Map__HexString__TypeName", 286 "String", "TypeName", false, 287 )) 288 ts.Accumulate(schema.SpawnString("HexString")) 289 ts.Accumulate(schema.SpawnMap("Map__String__TypeName", 290 "String", "TypeName", false, 291 )) 292 ts.Accumulate(schema.SpawnMap("Map__TypeName__Int", 293 "String", "Int", false, 294 )) 295 ts.Accumulate(schema.SpawnString("RepresentationKind")) // todo: RepresentationKind is supposed to be an enum, but we're puting it to a string atm. 296 ts.Accumulate(schema.SpawnStruct("TypeDefnStruct", 297 []schema.StructField{ 298 schema.SpawnStructField("fields", "Map__FieldName__StructField", false, false), // todo: dodging inline defn's again. 299 schema.SpawnStructField("representation", "StructRepresentation", false, false), 300 }, 301 schema.StructRepresentation_Map{}, 302 )) 303 ts.Accumulate(schema.SpawnMap("Map__FieldName__StructField", 304 "FieldName", "StructField", false, 305 )) 306 ts.Accumulate(schema.SpawnString("FieldName")) 307 ts.Accumulate(schema.SpawnStruct("StructField", 308 []schema.StructField{ 309 schema.SpawnStructField("type", "TypeNameOrInlineDefn", false, false), 310 schema.SpawnStructField("optional", "Bool", true, false), // todo: wants to use the "implicit" feature, but not supported yet 311 schema.SpawnStructField("nullable", "Bool", true, false), // todo: wants to use the "implicit" feature, but not supported yet 312 }, 313 schema.StructRepresentation_Map{}, 314 )) 315 ts.Accumulate(schema.SpawnUnion("StructRepresentation", 316 []schema.TypeName{ 317 "StructRepresentation_Map", 318 "StructRepresentation_Tuple", 319 "StructRepresentation_Stringpairs", 320 "StructRepresentation_Stringjoin", 321 "StructRepresentation_Listpairs", 322 }, 323 schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{ 324 "map": "StructRepresentation_Map", 325 "tuple": "StructRepresentation_Tuple", 326 "stringpairs": "StructRepresentation_Stringpairs", 327 "stringjoin": "StructRepresentation_Stringjoin", 328 "listpairs": "StructRepresentation_Listpairs", 329 }), 330 )) 331 ts.Accumulate(schema.SpawnStruct("StructRepresentation_Map", 332 []schema.StructField{ 333 schema.SpawnStructField("fields", "Map__FieldName__StructRepresentation_Map_FieldDetails", true, false), // todo: dodging inline defn's again. 334 }, 335 schema.StructRepresentation_Map{}, 336 )) 337 ts.Accumulate(schema.SpawnMap("Map__FieldName__StructRepresentation_Map_FieldDetails", 338 "FieldName", "StructRepresentation_Map_FieldDetails", false, 339 )) 340 ts.Accumulate(schema.SpawnStruct("StructRepresentation_Map_FieldDetails", 341 []schema.StructField{ 342 schema.SpawnStructField("rename", "String", true, false), 343 schema.SpawnStructField("implicit", "AnyScalar", true, false), 344 }, 345 schema.StructRepresentation_Map{}, 346 )) 347 ts.Accumulate(schema.SpawnStruct("StructRepresentation_Tuple", 348 []schema.StructField{ 349 schema.SpawnStructField("fieldOrder", "List__FieldName", true, false), // todo: dodging inline defn's again. 350 }, 351 schema.StructRepresentation_Map{}, 352 )) 353 ts.Accumulate(schema.SpawnList("List__FieldName", 354 "FieldName", false, 355 )) 356 ts.Accumulate(schema.SpawnStruct("StructRepresentation_Stringpairs", 357 []schema.StructField{ 358 schema.SpawnStructField("innerDelim", "String", false, false), 359 schema.SpawnStructField("entryDelim", "String", false, false), 360 }, 361 schema.StructRepresentation_Map{}, 362 )) 363 ts.Accumulate(schema.SpawnStruct("StructRepresentation_Stringjoin", 364 []schema.StructField{ 365 schema.SpawnStructField("join", "String", false, false), // review: "delim" would seem more consistent with others -- but this is currently what the schema-schema says. 366 schema.SpawnStructField("fieldOrder", "List__FieldName", true, false), // todo: dodging inline defn's again. 367 }, 368 schema.StructRepresentation_Map{}, 369 )) 370 ts.Accumulate(schema.SpawnStruct("StructRepresentation_Listpairs", 371 []schema.StructField{}, 372 schema.StructRepresentation_Map{}, 373 )) 374 ts.Accumulate(schema.SpawnStruct("TypeDefnEnum", 375 []schema.StructField{ 376 schema.SpawnStructField("members", "List__EnumMember", false, false), 377 schema.SpawnStructField("representation", "EnumRepresentation", false, false), 378 }, 379 schema.StructRepresentation_Map{}, 380 )) 381 ts.Accumulate(schema.SpawnStruct("Unit", // todo: we should formalize the introdution of unit as first class type kind. 382 []schema.StructField{}, 383 schema.StructRepresentation_Map{}, 384 )) 385 ts.Accumulate(schema.SpawnList("List__EnumMember", 386 "EnumMember", false, 387 )) 388 ts.Accumulate(schema.SpawnString("EnumMember")) 389 ts.Accumulate(schema.SpawnUnion("EnumRepresentation", 390 []schema.TypeName{ 391 "EnumRepresentation_String", 392 "EnumRepresentation_Int", 393 }, 394 schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{ 395 "string": "EnumRepresentation_String", 396 "int": "EnumRepresentation_Int", 397 }), 398 )) 399 ts.Accumulate(schema.SpawnMap("EnumRepresentation_String", 400 "EnumMember", "String", false, 401 )) 402 ts.Accumulate(schema.SpawnMap("EnumRepresentation_Int", 403 "EnumMember", "Int", false, 404 )) 405 ts.Accumulate(schema.SpawnStruct("TypeDefnUnit", 406 []schema.StructField{ 407 schema.SpawnStructField("representation", "UnitRepresentation", false, false), 408 }, 409 schema.StructRepresentation_Map{}, 410 )) 411 ts.Accumulate(schema.SpawnString("UnitRepresentation")) // TODO: enum 412 ts.Accumulate(schema.SpawnStruct("TypeDefnAny", 413 []schema.StructField{}, 414 schema.StructRepresentation_Map{}, 415 )) 416 ts.Accumulate(schema.SpawnStruct("TypeDefnCopy", 417 []schema.StructField{ 418 schema.SpawnStructField("fromType", "TypeName", false, false), 419 }, 420 schema.StructRepresentation_Map{}, 421 )) 422 ts.Accumulate(schema.SpawnUnion("AnyScalar", 423 []schema.TypeName{ 424 "Bool", 425 "String", 426 "Bytes", 427 "Int", 428 "Float", 429 }, 430 schema.SpawnUnionRepresentationKinded(map[datamodel.Kind]schema.TypeName{ 431 datamodel.Kind_Bool: "Bool", 432 datamodel.Kind_String: "String", 433 datamodel.Kind_Bytes: "Bytes", 434 datamodel.Kind_Int: "Int", 435 datamodel.Kind_Float: "Float", 436 }), 437 )) 438 439 if errs := ts.ValidateGraph(); errs != nil { 440 for _, err := range errs { 441 fmt.Printf("- %s\n", err) 442 } 443 panic("not happening") 444 } 445 446 TypeSystem = ts 447 448 Prototypes.Schema = bindnode.Prototype( 449 (*Schema)(nil), 450 TypeSystem.TypeByName("Schema"), 451 ) 452 }