mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-08-04 14:36:07 +00:00
58 lines
1.6 KiB
Go
58 lines
1.6 KiB
Go
package schema
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
)
|
|
|
|
type Builder interface {
|
|
Context() context.Context
|
|
Describe(valueType reflect.Type) (*Node, error)
|
|
FlattenStruct(node *Node, structType reflect.Type) error
|
|
Define(name string, build func() (*Node, error)) (*Node, error)
|
|
}
|
|
|
|
type Describer interface {
|
|
DescribeSchema(builder Builder) (*Node, error)
|
|
}
|
|
|
|
type UnionVariant struct {
|
|
Value any
|
|
StructType reflect.Type
|
|
TypeOptional bool
|
|
}
|
|
|
|
func DiscriminatedUnion(builder Builder, discriminatorKey string, discriminatorRequired bool, variants []UnionVariant, buildBase func(variant *Node) error) (*Node, error) {
|
|
variantNodes := make([]*Node, 0, len(variants))
|
|
for _, variant := range variants {
|
|
variantNode := StrictObject()
|
|
if variant.TypeOptional {
|
|
stringValue, isString := variant.Value.(string)
|
|
if !isString {
|
|
return nil, E.New("optional discriminator requires a string value")
|
|
}
|
|
variantNode.Properties.Put(discriminatorKey, StringEnum(stringValue, ""))
|
|
} else {
|
|
variantNode.Properties.Put(discriminatorKey, &Node{Const: variant.Value})
|
|
}
|
|
if discriminatorRequired || !variant.TypeOptional {
|
|
variantNode.Required = append(variantNode.Required, discriminatorKey)
|
|
}
|
|
if buildBase != nil {
|
|
err := buildBase(variantNode)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if variant.StructType != nil {
|
|
err := builder.FlattenStruct(variantNode, variant.StructType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
variantNodes = append(variantNodes, variantNode)
|
|
}
|
|
return OneOf(variantNodes...), nil
|
|
}
|