summaryrefslogtreecommitdiff
path: root/vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-24 17:58:01 -0600
committermo khan <mo@mokhan.ca>2025-07-24 17:58:01 -0600
commit72296119fc9755774719f8f625ad03e0e0ec457a (patch)
treeed236ddee12a20fb55b7cfecf13f62d3a000dcb5 /vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go
parenta920a8cfe415858bb2777371a77018599ffed23f (diff)
parenteaa1bd3b8e12934aed06413d75e7482ac58d805a (diff)
Merge branch 'the-spice-must-flow' into 'main'
Add SpiceDB Authorization See merge request gitlab-org/software-supply-chain-security/authorization/sparkled!19
Diffstat (limited to 'vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go')
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go139
1 files changed, 139 insertions, 0 deletions
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go b/vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go
new file mode 100644
index 0000000..7050c85
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go
@@ -0,0 +1,139 @@
+package json
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+)
+
+// DiscardUnknownField discards unknown fields from a decoder body.
+// This function is useful while deserializing a JSON body with additional
+// unknown information that should be discarded.
+func DiscardUnknownField(decoder *json.Decoder) error {
+ // This deliberately does not share logic with CollectUnknownField, even
+ // though it could, because if we were to delegate to that then we'd incur
+ // extra allocations and general memory usage.
+ v, err := decoder.Token()
+ if err == io.EOF {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+
+ if _, ok := v.(json.Delim); ok {
+ for decoder.More() {
+ err = DiscardUnknownField(decoder)
+ }
+ endToken, err := decoder.Token()
+ if err != nil {
+ return err
+ }
+ if _, ok := endToken.(json.Delim); !ok {
+ return fmt.Errorf("invalid JSON : expected json delimiter, found %T %v",
+ endToken, endToken)
+ }
+ }
+
+ return nil
+}
+
+// CollectUnknownField grabs the contents of unknown fields from the decoder body
+// and returns them as a byte slice. This is useful for skipping unknown fields without
+// completely discarding them.
+func CollectUnknownField(decoder *json.Decoder) ([]byte, error) {
+ result, err := collectUnknownField(decoder)
+ if err != nil {
+ return nil, err
+ }
+
+ buff := bytes.NewBuffer(nil)
+ encoder := json.NewEncoder(buff)
+
+ if err := encoder.Encode(result); err != nil {
+ return nil, err
+ }
+
+ return buff.Bytes(), nil
+}
+
+func collectUnknownField(decoder *json.Decoder) (interface{}, error) {
+ // Grab the initial value. This could either be a concrete value like a string or a a
+ // delimiter.
+ token, err := decoder.Token()
+ if err == io.EOF {
+ return nil, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ // If it's an array or object, we'll need to recurse.
+ delim, ok := token.(json.Delim)
+ if ok {
+ var result interface{}
+ if delim == '{' {
+ result, err = collectUnknownObject(decoder)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ result, err = collectUnknownArray(decoder)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Discard the closing token. decoder.Token handles checking for matching delimiters
+ if _, err := decoder.Token(); err != nil {
+ return nil, err
+ }
+ return result, nil
+ }
+
+ return token, nil
+}
+
+func collectUnknownArray(decoder *json.Decoder) ([]interface{}, error) {
+ // We need to create an empty array here instead of a nil array, since by getting
+ // into this function at all we necessarily have seen a non-nil list.
+ array := []interface{}{}
+
+ for decoder.More() {
+ value, err := collectUnknownField(decoder)
+ if err != nil {
+ return nil, err
+ }
+ array = append(array, value)
+ }
+
+ return array, nil
+}
+
+func collectUnknownObject(decoder *json.Decoder) (map[string]interface{}, error) {
+ object := make(map[string]interface{})
+
+ for decoder.More() {
+ key, err := collectUnknownField(decoder)
+ if err != nil {
+ return nil, err
+ }
+
+ // Keys have to be strings, which is particularly important as the encoder
+ // won't except a map with interface{} keys
+ stringKey, ok := key.(string)
+ if !ok {
+ return nil, fmt.Errorf("expected string key, found %T", key)
+ }
+
+ value, err := collectUnknownField(decoder)
+ if err != nil {
+ return nil, err
+ }
+
+ object[stringKey] = value
+ }
+
+ return object, nil
+}