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  }