Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "json",
srcs = [
"json.go",
"registry.go",
"stdlib.go",
],
importpath = "github.com/lestrrat-go/jwx/v3/internal/json",
visibility = ["//:__subpackages__"],
deps = ["//internal/base64"],
)
alias(
name = "go_default_library",
actual = ":json",
visibility = ["//:__subpackages__"],
)
+48
View File
@@ -0,0 +1,48 @@
//go:build jwx_goccy
package json
import (
"io"
"github.com/goccy/go-json"
)
type Decoder = json.Decoder
type Delim = json.Delim
type Encoder = json.Encoder
type Marshaler = json.Marshaler
type Number = json.Number
type RawMessage = json.RawMessage
type Unmarshaler = json.Unmarshaler
func Engine() string {
return "github.com/goccy/go-json"
}
// NewDecoder respects the values specified in DecoderSettings,
// and creates a Decoder that has certain features turned on/off
func NewDecoder(r io.Reader) *json.Decoder {
dec := json.NewDecoder(r)
if UseNumber() {
dec.UseNumber()
}
return dec
}
// NewEncoder is just a proxy for "encoding/json".NewEncoder
func NewEncoder(w io.Writer) *json.Encoder {
return json.NewEncoder(w)
}
// Marshal is just a proxy for "encoding/json".Marshal
func Marshal(v any) ([]byte, error) {
return json.Marshal(v)
}
// MarshalIndent is just a proxy for "encoding/json".MarshalIndent
func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
return json.MarshalIndent(v, prefix, indent)
}
+127
View File
@@ -0,0 +1,127 @@
package json
import (
"bytes"
"fmt"
"os"
"sync/atomic"
"github.com/lestrrat-go/jwx/v3/internal/base64"
)
var useNumber uint32 // TODO: at some point, change to atomic.Bool
func UseNumber() bool {
return atomic.LoadUint32(&useNumber) == 1
}
// Sets the global configuration for json decoding
func DecoderSettings(inUseNumber bool) {
var val uint32
if inUseNumber {
val = 1
}
atomic.StoreUint32(&useNumber, val)
}
// Unmarshal respects the values specified in DecoderSettings,
// and uses a Decoder that has certain features turned on/off
func Unmarshal(b []byte, v any) error {
dec := NewDecoder(bytes.NewReader(b))
return dec.Decode(v)
}
func AssignNextBytesToken(dst *[]byte, dec *Decoder) error {
var val string
if err := dec.Decode(&val); err != nil {
return fmt.Errorf(`error reading next value: %w`, err)
}
buf, err := base64.DecodeString(val)
if err != nil {
return fmt.Errorf(`expected base64 encoded []byte (%T)`, val)
}
*dst = buf
return nil
}
func ReadNextStringToken(dec *Decoder) (string, error) {
var val string
if err := dec.Decode(&val); err != nil {
return "", fmt.Errorf(`error reading next value: %w`, err)
}
return val, nil
}
func AssignNextStringToken(dst **string, dec *Decoder) error {
val, err := ReadNextStringToken(dec)
if err != nil {
return err
}
*dst = &val
return nil
}
// FlattenAudience is a flag to specify if we should flatten the "aud"
// entry to a string when there's only one entry.
// In jwx < 1.1.8 we just dumped everything as an array of strings,
// but apparently AWS Cognito doesn't handle this well.
//
// So now we have the ability to dump "aud" as a string if there's
// only one entry, but we need to retain the old behavior so that
// we don't accidentally break somebody else's code. (e.g. messing
// up how signatures are calculated)
var FlattenAudience uint32
func MarshalAudience(aud []string, flatten bool) ([]byte, error) {
var val any
if len(aud) == 1 && flatten {
val = aud[0]
} else {
val = aud
}
return Marshal(val)
}
func EncodeAudience(enc *Encoder, aud []string, flatten bool) error {
var val any
if len(aud) == 1 && flatten {
val = aud[0]
} else {
val = aud
}
return enc.Encode(val)
}
// DecodeCtx is an interface for objects that needs that extra something
// when decoding JSON into an object.
type DecodeCtx interface {
Registry() *Registry
}
// DecodeCtxContainer is used to differentiate objects that can carry extra
// decoding hints and those who can't.
type DecodeCtxContainer interface {
DecodeCtx() DecodeCtx
SetDecodeCtx(DecodeCtx)
}
// stock decodeCtx. should cover 80% of the cases
type decodeCtx struct {
registry *Registry
}
func NewDecodeCtx(r *Registry) DecodeCtx {
return &decodeCtx{registry: r}
}
func (dc *decodeCtx) Registry() *Registry {
return dc.registry
}
func Dump(v any) {
enc := NewEncoder(os.Stdout)
enc.SetIndent("", " ")
//nolint:errchkjson
_ = enc.Encode(v)
}
+90
View File
@@ -0,0 +1,90 @@
package json
import (
"fmt"
"reflect"
"sync"
)
// CustomDecoder is the interface we expect from RegisterCustomField in jws, jwe, jwk, and jwt packages.
type CustomDecoder interface {
// Decode takes a JSON encoded byte slice and returns the desired
// decoded value,which will be used as the value for that field
// registered through RegisterCustomField
Decode([]byte) (any, error)
}
// CustomDecodeFunc is a stateless, function-based implementation of CustomDecoder
type CustomDecodeFunc func([]byte) (any, error)
func (fn CustomDecodeFunc) Decode(data []byte) (any, error) {
return fn(data)
}
type objectTypeDecoder struct {
typ reflect.Type
name string
}
func (dec *objectTypeDecoder) Decode(data []byte) (any, error) {
ptr := reflect.New(dec.typ).Interface()
if err := Unmarshal(data, ptr); err != nil {
return nil, fmt.Errorf(`failed to decode field %s: %w`, dec.name, err)
}
return reflect.ValueOf(ptr).Elem().Interface(), nil
}
type Registry struct {
mu *sync.RWMutex
ctrs map[string]CustomDecoder
}
func NewRegistry() *Registry {
return &Registry{
mu: &sync.RWMutex{},
ctrs: make(map[string]CustomDecoder),
}
}
func (r *Registry) Register(name string, object any) {
if object == nil {
r.mu.Lock()
defer r.mu.Unlock()
delete(r.ctrs, name)
return
}
r.mu.Lock()
defer r.mu.Unlock()
if ctr, ok := object.(CustomDecoder); ok {
r.ctrs[name] = ctr
} else {
r.ctrs[name] = &objectTypeDecoder{
typ: reflect.TypeOf(object),
name: name,
}
}
}
func (r *Registry) Decode(dec *Decoder, name string) (any, error) {
r.mu.RLock()
defer r.mu.RUnlock()
if ctr, ok := r.ctrs[name]; ok {
var raw RawMessage
if err := dec.Decode(&raw); err != nil {
return nil, fmt.Errorf(`failed to decode field %s: %w`, name, err)
}
v, err := ctr.Decode([]byte(raw))
if err != nil {
return nil, fmt.Errorf(`failed to decode field %s: %w`, name, err)
}
return v, nil
}
var decoded any
if err := dec.Decode(&decoded); err != nil {
return nil, fmt.Errorf(`failed to decode field %s: %w`, name, err)
}
return decoded, nil
}
+47
View File
@@ -0,0 +1,47 @@
//go:build !jwx_goccy
//nolint:revive
package json
import (
"encoding/json"
"io"
)
type Decoder = json.Decoder
type Delim = json.Delim
type Encoder = json.Encoder
type Marshaler = json.Marshaler
type Number = json.Number
type RawMessage = json.RawMessage
type Unmarshaler = json.Unmarshaler
func Engine() string {
return "encoding/json"
}
// NewDecoder respects the values specified in DecoderSettings,
// and creates a Decoder that has certain features turned on/off
func NewDecoder(r io.Reader) *json.Decoder {
dec := json.NewDecoder(r)
if UseNumber() {
dec.UseNumber()
}
return dec
}
func NewEncoder(w io.Writer) *json.Encoder {
return json.NewEncoder(w)
}
// Marshal is just a proxy for "encoding/json".Marshal
func Marshal(v any) ([]byte, error) {
return json.Marshal(v)
}
// MarshalIndent is just a proxy for "encoding/json".MarshalIndent
func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
return json.MarshalIndent(v, prefix, indent)
}