Skip to content

Commit ccc3184

Browse files
add 'orderedmap' data structure
1 parent c3ea76f commit ccc3184

File tree

3 files changed

+170
-43
lines changed

3 files changed

+170
-43
lines changed

internal/cli/core/list.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func (ir coreListResult) String() string {
108108
t.SetHeader(tr("ID"), tr("Installed"), tr("Latest"), tr("Name"))
109109
for _, platform := range ir.platforms {
110110
name := ""
111-
if installed := platform.GetLatestRelease(); installed != nil {
111+
if installed := platform.GetInstalledRelease(); installed != nil {
112112
name = installed.Name
113113
}
114114
if name == "" {

internal/cli/feedback/result/rpc.go

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,48 +16,33 @@
1616
package result
1717

1818
import (
19-
"slices"
20-
19+
"github.com/arduino/arduino-cli/internal/orderedmap"
2120
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
22-
"github.com/iancoleman/orderedmap"
2321
semver "go.bug.st/relaxed-semver"
2422
)
2523

2624
// NewPlatformResult creates a new result.Platform from rpc.PlatformSummary
2725
func NewPlatformResult(in *rpc.PlatformSummary) *Platform {
28-
meta := in.Metadata
29-
res := &Platform{
30-
Id: meta.Id,
31-
Maintainer: meta.Maintainer,
32-
Website: meta.Website,
33-
Email: meta.Email,
34-
ManuallyInstalled: meta.ManuallyInstalled,
35-
Deprecated: meta.Deprecated,
36-
Indexed: meta.Indexed,
37-
38-
Releases: orderedmap.New(),
39-
InstalledVersion: in.InstalledVersion,
40-
LatestVersion: in.LatestVersion,
41-
}
42-
26+
releases := orderedmap.New[string, *PlatformRelease]()
4327
for k, v := range in.Releases {
44-
res.Releases.Set(k, NewPlatformReleaseResult(v))
28+
releases.Set(k, NewPlatformReleaseResult(v))
4529
}
46-
res.Releases.SortKeys(func(keys []string) {
47-
slices.SortFunc(keys, func(x, y string) int {
48-
return semver.ParseRelaxed(x).CompareTo(semver.ParseRelaxed(y))
49-
})
30+
releases.SortKeys(func(x, y string) int {
31+
return semver.ParseRelaxed(x).CompareTo(semver.ParseRelaxed(y))
5032
})
5133

52-
versions := []*semver.RelaxedVersion{}
53-
for version := range in.Releases {
54-
versions = append(versions, semver.ParseRelaxed(version))
34+
return &Platform{
35+
Id: in.Metadata.Id,
36+
Maintainer: in.Metadata.Maintainer,
37+
Website: in.Metadata.Website,
38+
Email: in.Metadata.Email,
39+
ManuallyInstalled: in.Metadata.ManuallyInstalled,
40+
Deprecated: in.Metadata.Deprecated,
41+
Indexed: in.Metadata.Indexed,
42+
Releases: releases,
43+
InstalledVersion: in.InstalledVersion,
44+
LatestVersion: in.LatestVersion,
5545
}
56-
slices.SortFunc(versions, (*semver.RelaxedVersion).CompareTo)
57-
for _, version := range versions {
58-
res.Releases.Set(version.String(), NewPlatformReleaseResult(in.Releases[version.String()]))
59-
}
60-
return res
6146
}
6247

6348
// Platform maps a rpc.Platform
@@ -70,28 +55,20 @@ type Platform struct {
7055
Deprecated bool `json:"deprecated,omitempty"`
7156
Indexed bool `json:"indexed,omitempty"`
7257

73-
Releases *orderedmap.OrderedMap `json:"releases,omitempty"`
58+
Releases *orderedmap.Map[string, *PlatformRelease] `json:"releases,omitempty"`
7459

7560
InstalledVersion string `json:"installed_version,omitempty"`
7661
LatestVersion string `json:"latest_version,omitempty"`
7762
}
7863

7964
// GetLatestRelease returns the latest relase of this platform or nil if none available.
8065
func (p *Platform) GetLatestRelease() *PlatformRelease {
81-
res, ok := p.Releases.Get(p.LatestVersion)
82-
if !ok {
83-
return nil
84-
}
85-
return res.(*PlatformRelease)
66+
return p.Releases.Get(p.LatestVersion)
8667
}
8768

8869
// GetInstalledRelease returns the installed relase of this platform or nil if none available.
8970
func (p *Platform) GetInstalledRelease() *PlatformRelease {
90-
res, ok := p.Releases.Get(p.InstalledVersion)
91-
if !ok {
92-
return nil
93-
}
94-
return res.(*PlatformRelease)
71+
return p.Releases.Get(p.InstalledVersion)
9572
}
9673

9774
// NewPlatformReleaseResult creates a new result.PlatformRelease from rpc.PlatformRelease

internal/orderedmap/orderedmap.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package orderedmap
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"reflect"
7+
"slices"
8+
)
9+
10+
// Map is a container of properties
11+
type Map[K comparable, V any] struct {
12+
kv map[K]V
13+
o []K
14+
}
15+
16+
// New returns a new Map
17+
func New[K comparable, V any]() *Map[K, V] {
18+
return &Map[K, V]{
19+
kv: map[K]V{},
20+
o: []K{},
21+
}
22+
}
23+
24+
// Get retrieves the value corresponding to key
25+
func (m *Map[K, V]) Get(key K) V {
26+
return m.kv[key]
27+
}
28+
29+
// GetOk retrieves the value corresponding to key and returns a true/false indicator
30+
// to check if the key is present in the map (true if the key is present)
31+
func (m *Map[K, V]) GetOk(key K) (V, bool) {
32+
v, ok := m.kv[key]
33+
return v, ok
34+
}
35+
36+
// ContainsKey returns true if the map contains the specified key
37+
func (m *Map[K, V]) ContainsKey(key K) bool {
38+
_, has := m.kv[key]
39+
return has
40+
}
41+
42+
// MarshalJSON marshal the map into json mantaining the order of the key
43+
func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
44+
if m.Size() == 0 {
45+
return []byte("{}"), nil
46+
}
47+
var buf bytes.Buffer
48+
buf.WriteByte('{')
49+
encoder := json.NewEncoder(&buf)
50+
for _, k := range m.o {
51+
if err := encoder.Encode(k); err != nil {
52+
return nil, err
53+
}
54+
buf.WriteByte(':')
55+
if err := encoder.Encode(m.kv[k]); err != nil {
56+
return nil, err
57+
}
58+
buf.WriteByte(',')
59+
}
60+
buf.Truncate(buf.Len() - 1) // remove last `,`
61+
buf.WriteByte('}')
62+
return buf.Bytes(), nil
63+
}
64+
65+
// Set inserts or replaces an existing key-value pair in the map
66+
func (m *Map[K, V]) Set(key K, value V) {
67+
if _, has := m.kv[key]; has {
68+
m.Remove(key)
69+
}
70+
m.kv[key] = value
71+
m.o = append(m.o, key)
72+
}
73+
74+
// Size returns the number of elements in the map
75+
func (m *Map[K, V]) Size() int {
76+
return len(m.kv)
77+
}
78+
79+
// Remove removes the key from the map
80+
func (m *Map[K, V]) Remove(key K) {
81+
delete(m.kv, key)
82+
for i, k := range m.o {
83+
if k == key {
84+
m.o = append(m.o[:i], m.o[i+1:]...)
85+
return
86+
}
87+
}
88+
}
89+
90+
// Merge merges other Maps into this one. Each key/value of the merged Maps replaces
91+
// the key/value present in the original Map.
92+
func (m *Map[K, V]) Merge(sources ...*Map[K, V]) *Map[K, V] {
93+
for _, source := range sources {
94+
for _, key := range source.o {
95+
value := source.kv[key]
96+
m.Set(key, value)
97+
}
98+
}
99+
return m
100+
}
101+
102+
// Keys returns an array of the keys contained in the Map
103+
func (m *Map[K, V]) Keys() []K {
104+
keys := make([]K, len(m.o))
105+
copy(keys, m.o)
106+
return keys
107+
}
108+
109+
func (m *Map[K, V]) SortKeys(f func(x, y K) int) {
110+
slices.SortFunc(m.o, f)
111+
}
112+
113+
func (m *Map[K, V]) SortStableKeys(f func(x, y K) int) {
114+
slices.SortStableFunc(m.o, f)
115+
}
116+
117+
// Values returns an array of the values contained in the Map. Duplicated
118+
// values are repeated in the list accordingly.
119+
func (m *Map[K, V]) Values() []V {
120+
values := make([]V, len(m.o))
121+
for i, key := range m.o {
122+
values[i] = m.kv[key]
123+
}
124+
return values
125+
}
126+
127+
// AsMap returns the underlying map[string]string. This is useful if you need to
128+
// for ... range but without the requirement of the ordered elements.
129+
func (m *Map[K, V]) AsMap() map[K]V {
130+
return m.kv
131+
}
132+
133+
// Clone makes a copy of the Map
134+
func (m *Map[K, V]) Clone() *Map[K, V] {
135+
clone := New[K, V]()
136+
clone.Merge(m)
137+
return clone
138+
}
139+
140+
// Equals returns true if the current Map contains the same key/value pairs of
141+
// the Map passed as argument, the order of insertion does not matter.
142+
func (m *Map[K, V]) Equals(other *Map[K, V]) bool {
143+
return reflect.DeepEqual(m.kv, other.kv)
144+
}
145+
146+
// EqualsWithOrder returns true if the current Map contains the same key/value pairs of
147+
// the Map passed as argument with the same order of insertion.
148+
func (m *Map[K, V]) EqualsWithOrder(other *Map[K, V]) bool {
149+
return reflect.DeepEqual(m.o, other.o) && reflect.DeepEqual(m.kv, other.kv)
150+
}

0 commit comments

Comments
 (0)