github.com/aristanetworks/gomap@v0.0.0-20240103001659-f6b0e31fb1a7/funcs.go (about)

     1  // Modifications copyright (c) Arista Networks, Inc. 2022
     2  // Underlying
     3  // Copyright 2014 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package gomap
     8  
     9  import (
    10  	"fmt"
    11  	"strings"
    12  
    13  	"golang.org/x/exp/slices"
    14  )
    15  
    16  // String converts m to a string representation using K's and E's
    17  // String functions.
    18  func String[K fmt.Stringer, E fmt.Stringer](m *Map[K, E]) string {
    19  	return StringFunc(m,
    20  		func(key K) string { return key.String() },
    21  		func(elem E) string { return elem.String() },
    22  	)
    23  }
    24  
    25  type strKE struct {
    26  	k string
    27  	e string
    28  }
    29  
    30  // StringFunc converts m to a string representation with the help of
    31  // strK and strE functions to stringify m's keys and elems.
    32  func StringFunc[K any, E any](m *Map[K, E],
    33  	strK func(key K) string,
    34  	strE func(elem E) string) string {
    35  	if m == nil || m.Len() == 0 {
    36  		return "gomap.Map[]"
    37  	}
    38  	strs := make([]strKE, m.Len())
    39  	s := 0
    40  	i := 0
    41  	for it := m.Iter(); it.Next(); {
    42  		ke := &strs[i]
    43  		ke.k = strK(it.Key())
    44  		ke.e = strE(it.Elem())
    45  		s += len(ke.k) + len(ke.e)
    46  		i++
    47  	}
    48  	slices.SortFunc(strs, func(a, b strKE) int {
    49  		if a.k < b.k {
    50  			return -1
    51  		}
    52  		if a.k > b.k {
    53  			return +1
    54  		}
    55  		return 0
    56  	})
    57  
    58  	var b strings.Builder
    59  	b.Grow(len("gomap.Map[]") + // space for header and footer
    60  		len(strs)*2 - 1 + // space for delimiters
    61  		s) // space for keys and elems
    62  	b.WriteString("gomap.Map[")
    63  	for i, ke := range strs {
    64  		if i != 0 {
    65  			b.WriteByte(' ')
    66  		}
    67  		b.WriteString(ke.k)
    68  		b.WriteByte(':')
    69  		b.WriteString(ke.e)
    70  	}
    71  	b.WriteByte(']')
    72  	return b.String()
    73  }
    74  
    75  // Equal returns true if the same set of keys and elems are in m1 and
    76  // m2. Elements are compared using ==.
    77  func Equal[K any, E comparable](m1, m2 *Map[K, E]) bool {
    78  	if m1.Len() != m2.Len() {
    79  		return false
    80  	}
    81  	for it := m1.Iter(); it.Next(); {
    82  		e2, ok := m2.Get(it.Key())
    83  		if !ok || it.Elem() != e2 {
    84  			return false
    85  		}
    86  	}
    87  	return true
    88  }
    89  
    90  // Equal returns true if the same set of keys and elems are in m1 and
    91  // m2. Elements are compared using eq.
    92  func EqualFunc[K, E any](m1, m2 *Map[K, E], eq func(E, E) bool) bool {
    93  	if m1.Len() != m2.Len() {
    94  		return false
    95  	}
    96  	for it := m1.Iter(); it.Next(); {
    97  		e2, ok := m2.Get(it.Key())
    98  		if !ok || !eq(it.Elem(), e2) {
    99  			return false
   100  		}
   101  	}
   102  	return true
   103  }