mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit to master@31c870e82a48
Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
145
vendor/github.com/secure-systems-lab/go-securesystemslib/cjson/canonicaljson.go
generated
vendored
Normal file
145
vendor/github.com/secure-systems-lab/go-securesystemslib/cjson/canonicaljson.go
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
package cjson
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
)
|
||||
|
||||
/*
|
||||
encodeCanonicalString is a helper function to canonicalize the passed string
|
||||
according to the OLPC canonical JSON specification for strings (see
|
||||
http://wiki.laptop.org/go/Canonical_JSON). String canonicalization consists of
|
||||
escaping backslashes ("\") and double quotes (") and wrapping the resulting
|
||||
string in double quotes (").
|
||||
*/
|
||||
func encodeCanonicalString(s string) string {
|
||||
re := regexp.MustCompile(`([\"\\])`)
|
||||
return fmt.Sprintf("\"%s\"", re.ReplaceAllString(s, "\\$1"))
|
||||
}
|
||||
|
||||
/*
|
||||
encodeCanonical is a helper function to recursively canonicalize the passed
|
||||
object according to the OLPC canonical JSON specification (see
|
||||
http://wiki.laptop.org/go/Canonical_JSON) and write it to the passed
|
||||
*bytes.Buffer. If canonicalization fails it returns an error.
|
||||
*/
|
||||
func encodeCanonical(obj interface{}, result *bytes.Buffer) (err error) {
|
||||
// Since this function is called recursively, we use panic if an error occurs
|
||||
// and recover in a deferred function, which is always called before
|
||||
// returning. There we set the error that is returned eventually.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = errors.New(r.(string))
|
||||
}
|
||||
}()
|
||||
|
||||
switch objAsserted := obj.(type) {
|
||||
case string:
|
||||
result.WriteString(encodeCanonicalString(objAsserted))
|
||||
|
||||
case bool:
|
||||
if objAsserted {
|
||||
result.WriteString("true")
|
||||
} else {
|
||||
result.WriteString("false")
|
||||
}
|
||||
|
||||
// The wrapping `EncodeCanonical` function decodes the passed json data with
|
||||
// `decoder.UseNumber` so that any numeric value is stored as `json.Number`
|
||||
// (instead of the default `float64`). This allows us to assert that it is a
|
||||
// non-floating point number, which are the only numbers allowed by the used
|
||||
// canonicalization specification.
|
||||
case json.Number:
|
||||
if _, err := objAsserted.Int64(); err != nil {
|
||||
panic(fmt.Sprintf("Can't canonicalize floating point number '%s'",
|
||||
objAsserted))
|
||||
}
|
||||
result.WriteString(objAsserted.String())
|
||||
|
||||
case nil:
|
||||
result.WriteString("null")
|
||||
|
||||
// Canonicalize slice
|
||||
case []interface{}:
|
||||
result.WriteString("[")
|
||||
for i, val := range objAsserted {
|
||||
if err := encodeCanonical(val, result); err != nil {
|
||||
return err
|
||||
}
|
||||
if i < (len(objAsserted) - 1) {
|
||||
result.WriteString(",")
|
||||
}
|
||||
}
|
||||
result.WriteString("]")
|
||||
|
||||
case map[string]interface{}:
|
||||
result.WriteString("{")
|
||||
|
||||
// Make a list of keys
|
||||
var mapKeys []string
|
||||
for key := range objAsserted {
|
||||
mapKeys = append(mapKeys, key)
|
||||
}
|
||||
// Sort keys
|
||||
sort.Strings(mapKeys)
|
||||
|
||||
// Canonicalize map
|
||||
for i, key := range mapKeys {
|
||||
// Note: `key` must be a `string` (see `case map[string]interface{}`) and
|
||||
// canonicalization of strings cannot err out (see `case string`), thus
|
||||
// no error handling is needed here.
|
||||
encodeCanonical(key, result)
|
||||
|
||||
result.WriteString(":")
|
||||
if err := encodeCanonical(objAsserted[key], result); err != nil {
|
||||
return err
|
||||
}
|
||||
if i < (len(mapKeys) - 1) {
|
||||
result.WriteString(",")
|
||||
}
|
||||
i++
|
||||
}
|
||||
result.WriteString("}")
|
||||
|
||||
default:
|
||||
// We recover in a deferred function defined above
|
||||
panic(fmt.Sprintf("Can't canonicalize '%s' of type '%s'",
|
||||
objAsserted, reflect.TypeOf(objAsserted)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
EncodeCanonical JSON canonicalizes the passed object and returns it as a byte
|
||||
slice. It uses the OLPC canonical JSON specification (see
|
||||
http://wiki.laptop.org/go/Canonical_JSON). If canonicalization fails the byte
|
||||
slice is nil and the second return value contains the error.
|
||||
*/
|
||||
func EncodeCanonical(obj interface{}) ([]byte, error) {
|
||||
// FIXME: Terrible hack to turn the passed struct into a map, converting
|
||||
// the struct's variable names to the json key names defined in the struct
|
||||
data, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var jsonMap interface{}
|
||||
|
||||
dec := json.NewDecoder(bytes.NewReader(data))
|
||||
dec.UseNumber()
|
||||
if err := dec.Decode(&jsonMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create a buffer and write the canonicalized JSON bytes to it
|
||||
var result bytes.Buffer
|
||||
if err := encodeCanonical(jsonMap, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Bytes(), nil
|
||||
}
|
Reference in New Issue
Block a user