Skip to content

Commit

Permalink
Use ordered maps
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre Fenoll <[email protected]>
  • Loading branch information
fenollp committed Jan 4, 2023
1 parent 2ed340d commit 0fedbbd
Show file tree
Hide file tree
Showing 35 changed files with 521 additions and 281 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: true
matrix:
go: ['1.16', '1.x']
go: ['1.x']
os:
- ubuntu-latest
- windows-latest
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:
run: |
! git grep -InE 'json:"' | grep -v _test.go | grep -v yaml:
- if: runner.os == 'Linux' && matrix.go != '1.16'
- if: runner.os == 'Linux'
name: nilness
run: go run golang.org/x/tools/go/analysis/passes/nilness/cmd/nilness@latest ./...

Expand Down
15 changes: 13 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/getkin/kin-openapi

go 1.16
go 1.18

require (
github.com/go-openapi/jsonpointer v0.19.5
Expand All @@ -9,6 +9,17 @@ require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/perimeterx/marshmallow v1.1.4
github.com/stretchr/testify v1.8.1
gopkg.in/yaml.v2 v2.4.0 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.5
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-openapi/swag v0.19.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -40,6 +44,8 @@ github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/wk8/go-ordered-map/v2 v2.1.5 h1:jLbYIFyWQMUwHLO20cImlCRBoNc5lp0nmE2dvwcxc7k=
github.com/wk8/go-ordered-map/v2 v2.1.5/go.mod h1:9Xvgm2mV2kSq2SAm0Y608tBmu8akTzI7c2bz7/G7ZN4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
12 changes: 6 additions & 6 deletions openapi2/openapi2.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type T struct {
Produces []string `json:"produces,omitempty" yaml:"produces,omitempty"`
Host string `json:"host,omitempty" yaml:"host,omitempty"`
BasePath string `json:"basePath,omitempty" yaml:"basePath,omitempty"`
Paths map[string]*PathItem `json:"paths,omitempty" yaml:"paths,omitempty"`
Paths *Paths `json:"paths,omitempty" yaml:"paths,omitempty"`
Definitions map[string]*openapi3.SchemaRef `json:"definitions,omitempty" yaml:"definitions,omitempty"`
Parameters map[string]*Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
Responses map[string]*Response `json:"responses,omitempty" yaml:"responses,omitempty"`
Expand Down Expand Up @@ -53,8 +53,8 @@ func (doc T) MarshalJSON() ([]byte, error) {
if x := doc.BasePath; x != "" {
m["basePath"] = x
}
if x := doc.Paths; len(x) != 0 {
m["paths"] = x
if x := doc.Paths; x.Len() != 0 {
m["paths"] = x.om
}
if x := doc.Definitions; len(x) != 0 {
m["definitions"] = x
Expand Down Expand Up @@ -106,12 +106,12 @@ func (doc *T) UnmarshalJSON(data []byte) error {

func (doc *T) AddOperation(path string, method string, operation *Operation) {
if doc.Paths == nil {
doc.Paths = make(map[string]*PathItem)
doc.Paths = NewPaths()
}
pathItem := doc.Paths[path]
pathItem := doc.Paths.Value(path)
if pathItem == nil {
pathItem = &PathItem{}
doc.Paths[path] = pathItem
doc.Paths.Set(path, pathItem)
}
pathItem.SetOperation(method, operation)
}
80 changes: 80 additions & 0 deletions openapi2/paths.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package openapi2

import (
"encoding/json"

orderedmap "github.com/wk8/go-ordered-map/v2"
)

type Paths struct {
om *orderedmap.OrderedMap[string, *PathItem]
}

// MarshalJSON returns the JSON encoding of Paths.
func (paths *Paths) MarshalJSON() ([]byte, error) {
if paths == nil || paths.om == nil {
return []byte("{}"), nil
}
return paths.om.MarshalJSON()
}

// UnmarshalJSON sets Paths to a copy of data.
func (paths *Paths) UnmarshalJSON(data []byte) error {
return json.Unmarshal(data, &paths.om)
}

func (paths *Paths) Value(key string) *PathItem {
// if paths == nil || paths.om == nil {
// return nil
// }
return paths.om.Value(key)
}

func (paths *Paths) Set(key string, value *PathItem) {
// if paths != nil || paths.om != nil {
_, _ = paths.om.Set(key, value)
// }
}

func (paths *Paths) Len() int {
if paths == nil || paths.om == nil {
return 0
}
return paths.om.Len()
}

func (paths *Paths) Iter() *pathsKV {
if paths == nil || paths.om == nil {
return nil
}
return (*pathsKV)(paths.om.Oldest())
}

type pathsKV orderedmap.Pair[string, *PathItem] //FIXME: pub?

func (pair *pathsKV) Next() *pathsKV {
ompair := (*orderedmap.Pair[string, *PathItem])(pair)
return (*pathsKV)(ompair.Next())
}

// NewPathsWithCapacity builds a paths object of the given capacity.
func NewPathsWithCapacity(cap int) *Paths {
return &Paths{om: orderedmap.New[string, *PathItem](cap)}
}

// NewPaths builds a paths object with path items in insertion order.
func NewPaths(opts ...NewPathsOption) *Paths {
paths := NewPathsWithCapacity(len(opts))
for _, opt := range opts {
opt(paths)
}
return paths
}

// NewPathsOption describes options to NewPaths func
type NewPathsOption func(*Paths)

// WithPath adds paths as an option to NewPaths
func WithPath(path string, pathItem *PathItem) NewPathsOption {
return func(paths *Paths) { paths.Set(path, pathItem) }
}
4 changes: 2 additions & 2 deletions openapi2conv/issue558_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ paths:
`
doc3, err := v2v3YAML([]byte(spec))
require.NoError(t, err)
require.NotEmpty(t, doc3.Paths["/test"].Get.Deprecated)
require.NotEmpty(t, doc3.Paths.Value("/test").Get.Deprecated)
_, err = yaml.Marshal(doc3)
require.NoError(t, err)

doc2, err := FromV3(doc3)
require.NoError(t, err)
require.NotEmpty(t, doc2.Paths["/test"].Get.Deprecated)
require.NotEmpty(t, doc2.Paths.Value("/test").Get.Deprecated)
}
4 changes: 2 additions & 2 deletions openapi2conv/issue573_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ func TestIssue573(t *testing.T) {

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

// Is "produces" is not explicitly specified, default to "application/json".
pingPostContent := v3.Paths["/ping"].Post.Responses["200"].Value.Content
pingPostContent := v3.Paths.Value("/ping").Post.Responses["200"].Value.Content
require.Len(t, pingPostContent, 1)
require.Contains(t, pingPostContent, "application/json")
}
33 changes: 18 additions & 15 deletions openapi2conv/openapi2_conv.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"sort"
"strings"

orderedmap "github.com/wk8/go-ordered-map/v2"

"github.com/getkin/kin-openapi/openapi2"
"github.com/getkin/kin-openapi/openapi3"
)
Expand Down Expand Up @@ -66,16 +68,16 @@ func ToV3(doc2 *openapi2.T) (*openapi3.T, error) {
}
}

if paths := doc2.Paths; len(paths) != 0 {
doc3Paths := make(map[string]*openapi3.PathItem, len(paths))
for path, pathItem := range paths {
if paths := doc2.Paths; paths.Len() != 0 {
doc3.Paths = openapi3.NewPathsWithCapacity(paths.Len())
for pair := paths.Iter(); pair != nil; pair = pair.Next() {
path, pathItem := pair.Key, pair.Value
r, err := ToV3PathItem(doc2, doc3.Components, pathItem, doc2.Consumes)
if err != nil {
return nil, err
}
doc3Paths[path] = r
doc3.Paths.Set(path, r)
}
doc3.Paths = doc3Paths
}

if responses := doc2.Responses; len(responses) != 0 {
Expand Down Expand Up @@ -540,9 +542,9 @@ func ToV3SecurityScheme(securityScheme *openapi2.SecurityScheme) (*openapi3.Secu
result.Type = "oauth2"
flows := &openapi3.OAuthFlows{}
result.Flows = flows
scopesMap := make(map[string]string)
scopesMap := orderedmap.New[string, string](len(securityScheme.Scopes))
for scope, desc := range securityScheme.Scopes {
scopesMap[scope] = desc
scopesMap.Set(scope, desc)
}
flow := &openapi3.OAuthFlow{
AuthorizationURL: securityScheme.AuthorizationURL,
Expand Down Expand Up @@ -611,7 +613,8 @@ func FromV3(doc3 *openapi3.T) (*openapi2.T, error) {
if isHTTP {
doc2.Schemes = append(doc2.Schemes, "http")
}
for path, pathItem := range doc3.Paths {
for pair := doc3.Paths.Iter(); pair != nil; pair = pair.Next() {
path, pathItem := pair.Key, pair.Value
if pathItem == nil {
continue
}
Expand All @@ -636,7 +639,7 @@ func FromV3(doc3 *openapi3.T) (*openapi2.T, error) {
params = append(params, p)
}
sort.Sort(params)
doc2.Paths[path].Parameters = params
doc2.Paths.Value(path).Parameters = params
}

for name, param := range doc3.Components.Parameters {
Expand Down Expand Up @@ -1155,9 +1158,9 @@ func FromV3SecurityScheme(doc3 *openapi3.T, ref *openapi3.SecuritySchemeRef) (*o
return nil, nil
}

result.Scopes = make(map[string]string, len(flow.Scopes))
for scope, desc := range flow.Scopes {
result.Scopes[scope] = desc
result.Scopes = make(map[string]string, flow.Scopes.Len())
for pair := flow.Scopes.Oldest(); pair != nil; pair = pair.Next() {
result.Scopes[pair.Key] = pair.Value
}
}
default:
Expand All @@ -1183,12 +1186,12 @@ func stripNonExtensions(extensions map[string]interface{}) map[string]interface{

func addPathExtensions(doc2 *openapi2.T, path string, extensions map[string]interface{}) {
if doc2.Paths == nil {
doc2.Paths = make(map[string]*openapi2.PathItem)
doc2.Paths = openapi2.NewPaths()
}
pathItem := doc2.Paths[path]
pathItem := doc2.Paths.Value(path)
if pathItem == nil {
pathItem = &openapi2.PathItem{}
doc2.Paths[path] = pathItem
doc2.Paths.Set(path, pathItem)
}
pathItem.Extensions = extensions
}
Loading

0 comments on commit 0fedbbd

Please sign in to comment.