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  }