github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/common/labelsort/labelsort.go (about)

     1  // Copyright 2016 The rkt Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // TODO(sur) contribute this to the appc spec
    16  
    17  package labelsort
    18  
    19  import (
    20  	"sort"
    21  
    22  	"github.com/appc/spec/schema/types"
    23  )
    24  
    25  var ranks = map[types.ACIdentifier]int{
    26  	"version": 0,
    27  	"os":      1,
    28  	"arch":    2,
    29  }
    30  
    31  // By is a functional type which compares two labels li, lj,
    32  // returning true if li < lj, else false.
    33  type By func(li, lj types.Label) bool
    34  
    35  // RankedName compares the label names of li, lj lexically
    36  // returning true if li.Name < lj.Name, else false.
    37  // The names "version", "os", and "arch" always have lower ranks in that order,
    38  // hence "version" < "os" < "arch" < [any other label name]
    39  func RankedName(li, lj types.Label) bool {
    40  	ri := rank(li.Name)
    41  	rj := rank(lj.Name)
    42  
    43  	if ri != rj {
    44  		return ri < rj
    45  	}
    46  
    47  	return li.Name < lj.Name
    48  }
    49  
    50  func rank(name types.ACIdentifier) int {
    51  	if i, ok := ranks[name]; ok {
    52  		return i
    53  	}
    54  
    55  	return len(ranks) + 1
    56  }
    57  
    58  var _ sort.Interface = (*byLabelSorter)(nil)
    59  
    60  type byLabelSorter struct {
    61  	labels types.Labels
    62  	by     By
    63  }
    64  
    65  func (by By) Sort(ls types.Labels) {
    66  	s := byLabelSorter{
    67  		labels: ls,
    68  		by:     by,
    69  	}
    70  
    71  	sort.Sort(&s)
    72  }
    73  
    74  func (s *byLabelSorter) Len() int {
    75  	return len(s.labels)
    76  }
    77  
    78  func (s *byLabelSorter) Less(i int, j int) bool {
    79  	return s.by(s.labels[i], s.labels[j])
    80  }
    81  
    82  func (s *byLabelSorter) Swap(i int, j int) {
    83  	s.labels[i], s.labels[j] = s.labels[j], s.labels[i]
    84  }