v.io/jiri@v0.0.0-20160715023856-abfb8b131290/profiles/versions.go (about) 1 // Copyright 2015 The Vanadium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package profiles 6 7 import ( 8 "bytes" 9 "fmt" 10 "reflect" 11 "sort" 12 "strings" 13 ) 14 15 // VersionInfo represents the supported and default versions offered 16 // by a profile and a map of versions to arbitrary metadata used internally 17 // by the profile implementation. 18 type VersionInfo struct { 19 name string 20 data map[string]interface{} 21 ordered []string 22 defaultVersion string 23 } 24 25 // NewVersionInfo creates a new instance of VersionInfo from the supplied 26 // map of supported versions and their associated metadata. The keys for 27 // this map are the supported version strings. The supplied defaultVersion 28 // will be used whenever a specific version is not requested. 29 func NewVersionInfo(name string, supported map[string]interface{}, defaultVersion string) *VersionInfo { 30 vi := &VersionInfo{} 31 vi.name = name 32 vi.data = make(map[string]interface{}, len(supported)) 33 vi.ordered = make([]string, 0, len(supported)) 34 for k, v := range supported { 35 vi.data[k] = v 36 vi.ordered = append(vi.ordered, k) 37 } 38 sort.Sort(sort.Reverse(sort.StringSlice(vi.ordered))) 39 vi.defaultVersion = defaultVersion 40 return vi 41 } 42 43 // Lookup returns the metadata associated with the requested version. 44 func (vi *VersionInfo) Lookup(version string, to interface{}) error { 45 if len(version) == 0 { 46 version = vi.defaultVersion 47 } 48 from, present := vi.data[version] 49 if !present { 50 return fmt.Errorf("unsupported version: %q for %s", version, vi) 51 } 52 // The stored value may or may not be a pointer. 53 fromV := reflect.Indirect(reflect.ValueOf(from)) 54 55 // Make sure that the type of the stored value is assignable to the 56 // type of pointer passed in. 57 fromVT := fromV.Type() 58 if !fromVT.AssignableTo(reflect.TypeOf(to).Elem()) { 59 return fmt.Errorf("mismatched types: %T not assignable to %T", from, to) 60 } 61 toV := reflect.ValueOf(to).Elem() 62 toV.Set(fromV) 63 return nil 64 } 65 66 // Select selects a version from the available ones that best matches 67 // the requested one. If requested is the emtpy string then the default 68 // version is returned, otherwise an exact match is required. 69 func (vi *VersionInfo) Select(requested string) (string, error) { 70 if len(requested) == 0 { 71 return vi.defaultVersion, nil 72 } 73 for _, version := range vi.ordered { 74 if requested == version { 75 return requested, nil 76 } 77 } 78 return "", fmt.Errorf("unsupported version: %q for %s", requested, vi) 79 } 80 81 // String returns a string representation of the VersionInfo, in particular 82 // it lists all of the supported versions with an asterisk next to the 83 // default. 84 func (vi *VersionInfo) String() string { 85 r := bytes.Buffer{} 86 for _, v := range vi.ordered { 87 r.WriteString(" " + v) 88 if v == vi.defaultVersion { 89 r.WriteString("*") 90 } 91 } 92 return strings.TrimLeft(r.String(), " ") 93 } 94 95 // Default returns the default version. 96 func (vi *VersionInfo) Default() string { 97 return vi.defaultVersion 98 } 99 100 // Supported returns the set of supported versions. 101 func (vi *VersionInfo) Supported() []string { 102 r := make([]string, len(vi.ordered)) 103 copy(r, vi.ordered) 104 return r 105 } 106 107 // IsTargetNewerThanDefault returns true if the supplied version is newer than 108 // the default. 109 func (vi *VersionInfo) IsTargetNewerThanDefault(version string) bool { 110 return vi.defaultVersion < version 111 } 112 113 // IsTargetOlderThanDefault returns true if the supplied version is older than 114 // the default. 115 func (vi *VersionInfo) IsTargetOlderThanDefault(version string) bool { 116 return vi.defaultVersion > version 117 }