packagemainimport("fmt""cuelang.org/go/cue""cuelang.org/go/cue/cuecontext""cuelang.org/go/cue/errors")constval=`
i: int
s: string
t: [string]: string
_h: int
_h: "hidden"
#d: int
#d: "bar"
`funcmain(){c:=cuecontext.New()v:=c.CompileString(val)// try out different validation schemesprintErr("loose error",loose(v))printErr("every error",every(v))printErr("strict error",strict(v))fmt.Printf("\nvalue:\n%#v\n",v)}funcprintErr(prefixstring,errerror){iferr!=nil{msg:=errors.Details(err,nil)fmt.Printf("%s:\n%s\n",prefix,msg)}}funcloose(vcue.Value)error{returnv.Validate(// not final or concretecue.Concrete(false),// check minimallycue.Definitions(false),cue.Hidden(false),cue.Optional(false),)}funcevery(vcue.Value)error{returnv.Validate(// not final or concretecue.Concrete(false),// check everythingcue.Definitions(true),cue.Hidden(true),cue.Optional(true),)}funcstrict(vcue.Value)error{returnv.Validate(// ensure final and concretecue.Final(),cue.Concrete(true),// check everythingcue.Definitions(true),cue.Hidden(true),cue.Optional(true),)}
go run validate.go
loose error:
#d: conflicting values int and "bar" (mismatched types int and string):
7:5
8:5
_h: conflicting values int and "hidden" (mismatched types int and string):
5:5
6:5
every error:
#d: conflicting values int and "bar" (mismatched types int and string):
7:5
8:5
_h: conflicting values int and "hidden" (mismatched types int and string):
5:5
6:5
strict error:
#d: conflicting values int and "bar" (mismatched types int and string):
7:5
8:5
_h: conflicting values int and "hidden" (mismatched types int and string):
5:5
6:5
value:
i: int
s: string
t: {
[string]: string
}
_h: _|_ // conflicting values int and "hidden" (mismatched types int and string)
#d: _|_ // conflicting values int and "bar" (mismatched types int and string)
packagemainimport("fmt""cuelang.org/go/cue""cuelang.org/go/cue/cuecontext""cuelang.org/go/cue/errors")constschema=`
v: {
i: int
s: string
}
`constval=`
v: {
i: "hello"
s: 1
}
`funcmain(){c:=cuecontext.New()s:=c.CompileString(schema,cue.Filename("schema.cue"))v:=c.CompileString(val,cue.Filename("val.cue"))// unify the schema and valueu:=s.Unify(v)// check for errors during unificationifu.Err()!=nil{msg:=errors.Details(u.Err(),nil)fmt.Printf("Unify Error:\n%s\n",msg)}// To get all errors, we need to validateerr:=u.Validate()iferr!=nil{msg:=errors.Details(err,nil)fmt.Printf("Validate Error:\n%s\n",msg)}// print ufmt.Printf("%#v\n",u)}
go run unify.go
Unify Error:
v.i: conflicting values int and "hello" (mismatched types int and string):
schema.cue:3:5
val.cue:3:5
Validate Error:
v.i: conflicting values int and "hello" (mismatched types int and string):
schema.cue:3:5
val.cue:3:5
v.s: conflicting values string and 1 (mismatched types string and int):
schema.cue:4:5
val.cue:4:5
v: {
i: _|_ // conflicting values int and "hello" (mismatched types int and string)
s: _|_ // conflicting values string and 1 (mismatched types string and int)
}
Subsume 是一种在格的概念下比较两个 Value 的关系的强力工具。
Subsume 会告诉你一个 Value 是不是另一个的实例。换句话说,他检查一个 Value 是否完全向后兼容另一个。
下面的例子里,我们对每一对 Value 检查两个方向的容纳情况。
每一对的两个方向,期待的情况是一个方向通过而另一个失败。
subsume.go
packagemainimport("fmt""cuelang.org/go/cue""cuelang.org/go/cue/cuecontext""cuelang.org/go/cue/errors")constschemaWithNumber=`
{
i: number
s: string
}
`constschemaWithInt=`
{
i: int
s: string
}
`constconstraint=`
{
i: >10 // this will only be subsumed by number, not int
s: =~"^foo"
}
`constval=`
{
i: 100
s: "foobar"
}
`constconstraintType=`
{
i: uint
s: string
}
`funcmain(){ctx:=cuecontext.New()sn:=ctx.CompileString(schemaWithNumber,cue.Filename("schema_number.cue"))si:=ctx.CompileString(schemaWithInt,cue.Filename("schema_int.cue"))c:=ctx.CompileString(constraint,cue.Filename("constraint.cue"))v:=ctx.CompileString(val,cue.Filename("val.cue"))b:=ctx.CompileString(constraintType,cue.Filename("bad.cue"))// check subsumptionsprintErr("sn > c",sn.Subsume(c))printErr("c > sn",c.Subsume(sn))printErr("sn > v",sn.Subsume(v))printErr("v > sn",v.Subsume(sn))// this seems not intuitive, we'll talk it laterprintErr("si > c",si.Subsume(c))printErr("c > si",c.Subsume(si))printErr("si > v",si.Subsume(v))printErr("v > si",v.Subsume(si))printErr("s > b",si.Subsume(b))printErr("b > v",b.Subsume(v))}funcprintErr(prefixstring,errerror){iferr!=nil{msg:=errors.Details(err,nil)fmt.Printf("%s:\n%s\n",prefix,msg)}}
go run subsume.go
c > sn:
field i not present in {i:number,s:string}:
schema_number.cue:2:1
missing field "i"
v > sn:
field i not present in {i:number,s:string}:
schema_number.cue:2:1
missing field "i"
si > c:
field i not present in {i:>10,s:=~"^foo"}:
constraint.cue:2:1
missing field "i"
c > si:
field i not present in {i:int,s:string}:
schema_int.cue:2:1
missing field "i"
v > si:
field i not present in {i:int,s:string}:
schema_int.cue:2:1
missing field "i"