github.com/dahs81/otto@v0.2.1-0.20160126165905-6400716cf085/app/tuple.go (about) 1 package app 2 3 import ( 4 "fmt" 5 ) 6 7 // Tuple is the tupled used for looking up the App implementation 8 // for an Appfile. This struct is usually used in its non-pointer form, to be 9 // a key for maps. 10 type Tuple struct { 11 App string // App is the app type, i.e. "go" 12 Infra string // Infra is the infra type, i.e. "aws" 13 InfraFlavor string // InfraFlavor is the flavor, i.e. "vpc-public-private" 14 } 15 16 func (t Tuple) String() string { 17 return fmt.Sprintf("(%q, %q, %q)", t.App, t.Infra, t.InfraFlavor) 18 } 19 20 // TupleSlice is an alias of []Tuple that implements sort.Interface for 21 // sorting tuples. See the tests in tuple_test.go to see the sorting order. 22 type TupleSlice []Tuple 23 24 // sort.Interface impl. 25 func (s TupleSlice) Len() int { return len(s) } 26 func (s TupleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 27 func (s TupleSlice) Less(i, j int) bool { 28 if s[i].App != s[j].App { 29 return s[i].App < s[j].App 30 } 31 32 if s[i].Infra != s[j].Infra { 33 return s[i].Infra < s[j].Infra 34 } 35 36 if s[i].InfraFlavor != s[j].InfraFlavor { 37 return s[i].InfraFlavor < s[j].InfraFlavor 38 } 39 40 return false 41 } 42 43 // Map turns a TupleSlice into a map where all the tuples in the slice 44 // are mapped to a single factory function. 45 func (s TupleSlice) Map(f Factory) TupleMap { 46 m := make(TupleMap, len(s)) 47 for _, t := range s { 48 m[t] = f 49 } 50 51 return m 52 } 53 54 // TupleMap is an alias of map[Tuple]Factory that adds additional helper 55 // methods on top to help work with app tuples. 56 type TupleMap map[Tuple]Factory 57 58 // Lookup looks up a Tuple. This should be used instead of direct [] access 59 // since it respects wildcards ('*') within the Tuple. 60 func (m TupleMap) Lookup(t Tuple) Factory { 61 // If it just exists, return it 62 if f, ok := m[t]; ok { 63 return f 64 } 65 66 // Eh, this isn't terrible complexity, but we should probably look 67 // to do better than this at some point. 68 for h, f := range m { 69 if h.App != "*" && h.App != t.App { 70 continue 71 } 72 if h.Infra != "*" && h.Infra != t.Infra { 73 continue 74 } 75 if h.InfraFlavor != "*" && h.InfraFlavor != t.InfraFlavor { 76 continue 77 } 78 79 return f 80 } 81 82 return nil 83 } 84 85 // Add is a helper to add another map to this one. 86 func (m TupleMap) Add(m2 TupleMap) { 87 for k, v := range m2 { 88 m[k] = v 89 } 90 }