garm/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go
Gabriel Adrian Samfira 0093393bc3 Update all dependencies
Note: should we ditch vendoring?

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
2025-09-29 13:30:24 +03:00

125 lines
3.5 KiB
Go

// Copyright 2015 go-swagger maintainers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package jsonutils
import (
"iter"
"github.com/go-openapi/swag/jsonutils/adapters"
"github.com/go-openapi/swag/typeutils"
)
// JSONMapSlice represents a JSON object, with the order of keys maintained.
//
// It behaves like an ordered map, but keys can't be accessed in constant time.
type JSONMapSlice []JSONMapItem
// OrderedItems iterates over all (key,value) pairs with the order of keys maintained.
//
// This implements the [ifaces.Ordered] interface, so that [ifaces.Adapter] s know how to marshal
// keys in the desired order.
func (s JSONMapSlice) OrderedItems() iter.Seq2[string, any] {
return func(yield func(string, any) bool) {
for _, item := range s {
if !yield(item.Key, item.Value) {
return
}
}
}
}
// SetOrderedItems sets keys in the [JSONMapSlice] objects, as presented by
// the provided iterator.
//
// As a special case, if items is nil, this sets to receiver to a nil slice.
//
// This implements the [ifaces.SetOrdered] interface, so that [ifaces.Adapter] s know how to unmarshal
// keys in the desired order.
func (s *JSONMapSlice) SetOrderedItems(items iter.Seq2[string, any]) {
if items == nil {
// force receiver to be a nil slice
*s = nil
return
}
m := *s
if len(m) > 0 {
// update mode: short-circuited when unmarshaling fresh data structures
idx := make(map[string]int, len(m))
for i, item := range m {
idx[item.Key] = i
}
for k, v := range items {
idx, ok := idx[k]
if ok {
m[idx].Value = v
continue
}
m = append(m, JSONMapItem{Key: k, Value: v})
}
*s = m
return
}
for k, v := range items {
m = append(m, JSONMapItem{Key: k, Value: v})
}
*s = m
}
// MarshalJSON renders a [JSONMapSlice] as JSON bytes, preserving the order of keys.
//
// It will pick the JSON library currently configured by the [adapters.Registry] (defaults to the standard library).
func (s JSONMapSlice) MarshalJSON() ([]byte, error) {
orderedMarshaler := adapters.OrderedMarshalAdapterFor(s)
defer orderedMarshaler.Redeem()
return orderedMarshaler.OrderedMarshal(s)
}
// UnmarshalJSON builds a [JSONMapSlice] from JSON bytes, preserving the order of keys.
//
// Inner objects are unmarshaled as ordered [JSONMapSlice] slices and not map[string]any.
//
// It will pick the JSON library currently configured by the [adapters.Registry] (defaults to the standard library).
func (s *JSONMapSlice) UnmarshalJSON(data []byte) error {
if typeutils.IsNil(*s) {
// allow to unmarshal with a simple var declaration (nil slice)
*s = JSONMapSlice{}
}
orderedUnmarshaler := adapters.OrderedUnmarshalAdapterFor(s)
defer orderedUnmarshaler.Redeem()
return orderedUnmarshaler.OrderedUnmarshal(data, s)
}
// JSONMapItem represents the value of a key in a JSON object held by [JSONMapSlice].
//
// Notice that JSONMapItem should not be marshaled to or unmarshaled from JSON directly.
//
// Use this type as part of a [JSONMapSlice] when dealing with JSON bytes.
type JSONMapItem struct {
Key string
Value any
}