| package cty |
| |
| import ( |
| "fmt" |
| ) |
| |
| type typeTuple struct { |
| typeImplSigil |
| ElemTypes []Type |
| } |
| |
| // Tuple creates a tuple type with the given element types. |
| // |
| // After a slice is passed to this function the caller must no longer access |
| // the underlying array, since ownership is transferred to this library. |
| func Tuple(elemTypes []Type) Type { |
| return Type{ |
| typeTuple{ |
| ElemTypes: elemTypes, |
| }, |
| } |
| } |
| |
| func (t typeTuple) Equals(other Type) bool { |
| if ot, ok := other.typeImpl.(typeTuple); ok { |
| if len(t.ElemTypes) != len(ot.ElemTypes) { |
| // Fast path: if we don't have the same number of elements |
| // then we can't possibly be equal. |
| return false |
| } |
| |
| for i, ty := range t.ElemTypes { |
| oty := ot.ElemTypes[i] |
| if !ok { |
| return false |
| } |
| if !oty.Equals(ty) { |
| return false |
| } |
| } |
| |
| return true |
| } |
| return false |
| } |
| |
| func (t typeTuple) FriendlyName(mode friendlyTypeNameMode) string { |
| // There isn't really a friendly way to write a tuple type due to its |
| // complexity, so we'll just do something English-ish. Callers will |
| // probably want to make some extra effort to avoid ever printing out |
| // a tuple type FriendlyName in its entirety. For example, could |
| // produce an error message by diffing two object types and saying |
| // something like "Expected attribute foo to be string, but got number". |
| // TODO: Finish this |
| return "tuple" |
| } |
| |
| func (t typeTuple) GoString() string { |
| if len(t.ElemTypes) == 0 { |
| return "cty.EmptyTuple" |
| } |
| return fmt.Sprintf("cty.Tuple(%#v)", t.ElemTypes) |
| } |
| |
| // EmptyTuple is a shorthand for Tuple([]Type{}), to more easily talk about |
| // the empty tuple type. |
| var EmptyTuple Type |
| |
| // EmptyTupleVal is the only possible non-null, non-unknown value of type |
| // EmptyTuple. |
| var EmptyTupleVal Value |
| |
| func init() { |
| EmptyTuple = Tuple([]Type{}) |
| EmptyTupleVal = Value{ |
| ty: EmptyTuple, |
| v: []interface{}{}, |
| } |
| } |
| |
| // IsTupleType returns true if the given type is an object type, regardless |
| // of its element type. |
| func (t Type) IsTupleType() bool { |
| _, ok := t.typeImpl.(typeTuple) |
| return ok |
| } |
| |
| // Length returns the number of elements of the receiving tuple type. |
| // Will panic if the reciever isn't a tuple type; use IsTupleType to determine |
| // whether this operation will succeed. |
| func (t Type) Length() int { |
| if ot, ok := t.typeImpl.(typeTuple); ok { |
| return len(ot.ElemTypes) |
| } |
| panic("Length on non-tuple Type") |
| } |
| |
| // TupleElementType returns the type of the element with the given index. Will |
| // panic if the receiver is not a tuple type (use IsTupleType to confirm) |
| // or if the index is out of range (use Length to confirm). |
| func (t Type) TupleElementType(idx int) Type { |
| if ot, ok := t.typeImpl.(typeTuple); ok { |
| return ot.ElemTypes[idx] |
| } |
| panic("TupleElementType on non-tuple Type") |
| } |
| |
| // TupleElementTypes returns a slice of the recieving tuple type's element |
| // types. Will panic if the receiver is not a tuple type (use IsTupleType |
| // to confirm). |
| // |
| // The returned slice is part of the internal state of the type, and is provided |
| // for read access only. It is forbidden for any caller to modify the |
| // underlying array. For many purposes the element-related methods of Value |
| // are more appropriate and more convenient to use. |
| func (t Type) TupleElementTypes() []Type { |
| if ot, ok := t.typeImpl.(typeTuple); ok { |
| return ot.ElemTypes |
| } |
| panic("TupleElementTypes on non-tuple Type") |
| } |