Skip to content

Commit 1afb638

Browse files
committed
Use ordered maps
Signed-off-by: Pierre Fenoll <[email protected]>
1 parent 1f680b5 commit 1afb638

33 files changed

+513
-238
lines changed

.github/workflows/go.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
fail-fast: true
1414
matrix:
15-
go: ['1.16', '1.x']
15+
go: ['1.x']
1616
os:
1717
- ubuntu-latest
1818
- windows-latest
@@ -88,7 +88,7 @@ jobs:
8888
run: |
8989
! git grep -InE 'json:"' | grep -v _test.go | grep -v yaml:
9090
91-
- if: runner.os == 'Linux' && matrix.go != '1.16'
91+
- if: runner.os == 'Linux'
9292
name: nilness
9393
run: go run golang.org/x/tools/go/analysis/passes/nilness/cmd/nilness@latest ./...
9494

go.mod

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
module github.com/getkin/kin-openapi
22

3-
go 1.16
3+
go 1.18
44

55
require (
66
github.com/go-openapi/jsonpointer v0.19.5
77
github.com/gorilla/mux v1.8.0
88
github.com/invopop/yaml v0.1.0
99
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
1010
github.com/stretchr/testify v1.8.1
11-
gopkg.in/yaml.v2 v2.4.0 // indirect
11+
github.com/wk8/go-ordered-map/v2 v2.1.5
1212
gopkg.in/yaml.v3 v3.0.1
1313
)
14+
15+
require (
16+
github.com/bahlo/generic-list-go v0.2.0 // indirect
17+
github.com/buger/jsonparser v1.1.1 // indirect
18+
github.com/davecgh/go-spew v1.1.1 // indirect
19+
github.com/go-openapi/swag v0.19.5 // indirect
20+
github.com/josharian/intern v1.0.0 // indirect
21+
github.com/mailru/easyjson v0.7.7 // indirect
22+
github.com/pmezard/go-difflib v1.0.0 // indirect
23+
gopkg.in/yaml.v2 v2.4.0 // indirect
24+
)

go.sum

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
2+
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
3+
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
4+
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
15
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
26
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
37
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -9,14 +13,17 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
913
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
1014
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
1115
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
16+
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
17+
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
1218
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
1319
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
1420
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
1521
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
1622
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
1723
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
18-
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
1924
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
25+
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
26+
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
2027
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
2128
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
2229
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -29,6 +36,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
2936
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
3037
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
3138
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
39+
github.com/wk8/go-ordered-map/v2 v2.1.5 h1:jLbYIFyWQMUwHLO20cImlCRBoNc5lp0nmE2dvwcxc7k=
40+
github.com/wk8/go-ordered-map/v2 v2.1.5/go.mod h1:9Xvgm2mV2kSq2SAm0Y608tBmu8akTzI7c2bz7/G7ZN4=
3241
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3342
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
3443
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

openapi2/openapi2.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type T struct {
2020
Produces []string `json:"produces,omitempty" yaml:"produces,omitempty"`
2121
Host string `json:"host,omitempty" yaml:"host,omitempty"`
2222
BasePath string `json:"basePath,omitempty" yaml:"basePath,omitempty"`
23-
Paths map[string]*PathItem `json:"paths,omitempty" yaml:"paths,omitempty"`
23+
Paths *Paths `json:"paths,omitempty" yaml:"paths,omitempty"`
2424
Definitions map[string]*openapi3.SchemaRef `json:"definitions,omitempty" yaml:"definitions,omitempty"`
2525
Parameters map[string]*Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
2626
Responses map[string]*Response `json:"responses,omitempty" yaml:"responses,omitempty"`
@@ -41,12 +41,12 @@ func (doc *T) UnmarshalJSON(data []byte) error {
4141

4242
func (doc *T) AddOperation(path string, method string, operation *Operation) {
4343
if doc.Paths == nil {
44-
doc.Paths = make(map[string]*PathItem)
44+
doc.Paths = NewPaths()
4545
}
46-
pathItem := doc.Paths[path]
46+
pathItem := doc.Paths.Value(path)
4747
if pathItem == nil {
4848
pathItem = &PathItem{}
49-
doc.Paths[path] = pathItem
49+
doc.Paths.Set(path, pathItem)
5050
}
5151
pathItem.SetOperation(method, operation)
5252
}

openapi2/paths.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package openapi2
2+
3+
import (
4+
"encoding/json"
5+
6+
orderedmap "github.com/wk8/go-ordered-map/v2"
7+
)
8+
9+
type Paths struct {
10+
om *orderedmap.OrderedMap[string, *PathItem]
11+
}
12+
13+
// MarshalJSON returns the JSON encoding of Paths.
14+
func (paths *Paths) MarshalJSON() ([]byte, error) {
15+
if paths == nil || paths.om == nil {
16+
return []byte("{}"), nil
17+
}
18+
return paths.om.MarshalJSON()
19+
}
20+
21+
// UnmarshalJSON sets Paths to a copy of data.
22+
func (paths *Paths) UnmarshalJSON(data []byte) error {
23+
return json.Unmarshal(data, &paths.om)
24+
}
25+
26+
func (paths *Paths) Value(key string) *PathItem {
27+
// if paths == nil || paths.om == nil {
28+
// return nil
29+
// }
30+
return paths.om.Value(key)
31+
}
32+
33+
func (paths *Paths) Set(key string, value *PathItem) {
34+
// if paths != nil || paths.om != nil {
35+
_, _ = paths.om.Set(key, value)
36+
// }
37+
}
38+
39+
func (paths *Paths) Len() int {
40+
if paths == nil || paths.om == nil {
41+
return 0
42+
}
43+
return paths.om.Len()
44+
}
45+
46+
func (paths *Paths) Iter() *pathsKV {
47+
if paths == nil || paths.om == nil {
48+
return nil
49+
}
50+
return (*pathsKV)(paths.om.Oldest())
51+
}
52+
53+
type pathsKV orderedmap.Pair[string, *PathItem] //FIXME: pub?
54+
55+
func (pair *pathsKV) Next() *pathsKV {
56+
ompair := (*orderedmap.Pair[string, *PathItem])(pair)
57+
return (*pathsKV)(ompair.Next())
58+
}
59+
60+
// NewPathsWithCapacity builds a paths object of the given capacity.
61+
func NewPathsWithCapacity(cap int) *Paths {
62+
return &Paths{om: orderedmap.New[string, *PathItem](cap)}
63+
}
64+
65+
// NewPaths builds a paths object with path items in insertion order.
66+
func NewPaths(opts ...NewPathsOption) *Paths {
67+
paths := NewPathsWithCapacity(len(opts))
68+
for _, opt := range opts {
69+
opt(paths)
70+
}
71+
return paths
72+
}
73+
74+
// NewPathsOption describes options to NewPaths func
75+
type NewPathsOption func(*Paths)
76+
77+
// WithPath adds paths as an option to NewPaths
78+
func WithPath(path string, pathItem *PathItem) NewPathsOption {
79+
return func(paths *Paths) { paths.Set(path, pathItem) }
80+
}

openapi2conv/issue558_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ paths:
2727
`
2828
doc3, err := v2v3YAML([]byte(spec))
2929
require.NoError(t, err)
30-
require.NotEmpty(t, doc3.Paths["/test"].Get.Deprecated)
30+
require.NotEmpty(t, doc3.Paths.Value("/test").Get.Deprecated)
3131
_, err = yaml.Marshal(doc3)
3232
require.NoError(t, err)
3333

3434
doc2, err := FromV3(doc3)
3535
require.NoError(t, err)
36-
require.NotEmpty(t, doc2.Paths["/test"].Get.Deprecated)
36+
require.NotEmpty(t, doc2.Paths.Value("/test").Get.Deprecated)
3737
}

openapi2conv/issue573_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ func TestIssue573(t *testing.T) {
3636

3737
// Make sure the response content appears for each mime-type originally
3838
// appeared in "produces".
39-
pingGetContent := v3.Paths["/ping"].Get.Responses["200"].Value.Content
39+
pingGetContent := v3.Paths.Value("/ping").Get.Responses["200"].Value.Content
4040
require.Len(t, pingGetContent, 2)
4141
require.Contains(t, pingGetContent, "application/toml")
4242
require.Contains(t, pingGetContent, "application/xml")
4343

4444
// Is "produces" is not explicitly specified, default to "application/json".
45-
pingPostContent := v3.Paths["/ping"].Post.Responses["200"].Value.Content
45+
pingPostContent := v3.Paths.Value("/ping").Post.Responses["200"].Value.Content
4646
require.Len(t, pingPostContent, 1)
4747
require.Contains(t, pingPostContent, "application/json")
4848
}

openapi2conv/openapi2_conv.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"sort"
99
"strings"
1010

11+
orderedmap "github.com/wk8/go-ordered-map/v2"
12+
1113
"github.com/getkin/kin-openapi/openapi2"
1214
"github.com/getkin/kin-openapi/openapi3"
1315
)
@@ -69,16 +71,16 @@ func ToV3(doc2 *openapi2.T) (*openapi3.T, error) {
6971
}
7072
}
7173

72-
if paths := doc2.Paths; len(paths) != 0 {
73-
doc3Paths := make(map[string]*openapi3.PathItem, len(paths))
74-
for path, pathItem := range paths {
74+
if paths := doc2.Paths; paths.Len() != 0 {
75+
doc3.Paths = openapi3.NewPathsWithCapacity(paths.Len())
76+
for pair := paths.Iter(); pair != nil; pair = pair.Next() {
77+
path, pathItem := pair.Key, pair.Value
7578
r, err := ToV3PathItem(doc2, &doc3.Components, pathItem, doc2.Consumes)
7679
if err != nil {
7780
return nil, err
7881
}
79-
doc3Paths[path] = r
82+
doc3.Paths.Set(path, r)
8083
}
81-
doc3.Paths = doc3Paths
8284
}
8385

8486
if responses := doc2.Responses; len(responses) != 0 {
@@ -556,9 +558,9 @@ func ToV3SecurityScheme(securityScheme *openapi2.SecurityScheme) (*openapi3.Secu
556558
result.Type = "oauth2"
557559
flows := &openapi3.OAuthFlows{}
558560
result.Flows = flows
559-
scopesMap := make(map[string]string)
561+
scopesMap := orderedmap.New[string, string](len(securityScheme.Scopes))
560562
for scope, desc := range securityScheme.Scopes {
561-
scopesMap[scope] = desc
563+
scopesMap.Set(scope, desc)
562564
}
563565
flow := &openapi3.OAuthFlow{
564566
AuthorizationURL: securityScheme.AuthorizationURL,
@@ -628,7 +630,8 @@ func FromV3(doc3 *openapi3.T) (*openapi2.T, error) {
628630
if isHTTP {
629631
doc2.Schemes = append(doc2.Schemes, "http")
630632
}
631-
for path, pathItem := range doc3.Paths {
633+
for pair := doc3.Paths.Iter(); pair != nil; pair = pair.Next() {
634+
path, pathItem := pair.Key, pair.Value
632635
if pathItem == nil {
633636
continue
634637
}
@@ -654,7 +657,7 @@ func FromV3(doc3 *openapi3.T) (*openapi2.T, error) {
654657
params = append(params, p)
655658
}
656659
sort.Sort(params)
657-
doc2.Paths[path].Parameters = params
660+
doc2.Paths.Value(path).Parameters = params
658661
}
659662

660663
for name, param := range doc3.Components.Parameters {
@@ -1179,9 +1182,9 @@ func FromV3SecurityScheme(doc3 *openapi3.T, ref *openapi3.SecuritySchemeRef) (*o
11791182
return nil, nil
11801183
}
11811184

1182-
result.Scopes = make(map[string]string, len(flow.Scopes))
1183-
for scope, desc := range flow.Scopes {
1184-
result.Scopes[scope] = desc
1185+
result.Scopes = make(map[string]string, flow.Scopes.Len())
1186+
for pair := flow.Scopes.Oldest(); pair != nil; pair = pair.Next() {
1187+
result.Scopes[pair.Key] = pair.Value
11851188
}
11861189
}
11871190
default:
@@ -1205,12 +1208,12 @@ func stripNonCustomExtensions(extensions map[string]interface{}) {
12051208

12061209
func addPathExtensions(doc2 *openapi2.T, path string, extensionProps openapi3.ExtensionProps) {
12071210
if doc2.Paths == nil {
1208-
doc2.Paths = make(map[string]*openapi2.PathItem)
1211+
doc2.Paths = openapi2.NewPaths()
12091212
}
1210-
pathItem := doc2.Paths[path]
1213+
pathItem := doc2.Paths.Value(path)
12111214
if pathItem == nil {
12121215
pathItem = &openapi2.PathItem{}
1213-
doc2.Paths[path] = pathItem
1216+
doc2.Paths.Set(path, pathItem)
12141217
}
12151218
pathItem.ExtensionProps = extensionProps
12161219
}

0 commit comments

Comments
 (0)