cuelang.org/go@v0.13.0/internal/encoding/yaml/validate.go (about) 1 // Copyright 2025 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package yaml 16 17 import ( 18 "errors" 19 "io" 20 21 "cuelang.org/go/cue" 22 "cuelang.org/go/internal/core/adt" 23 "cuelang.org/go/internal/pkg" 24 "cuelang.org/go/internal/value" 25 ) 26 27 // Validate validates YAML and confirms it is an instance of schema. 28 // If the YAML source is a stream, every object must match v. 29 // 30 // If Validate is called in a broader context, like a validation or function 31 // call, the cycle context of n should be accumulated in c before this call. 32 // This can be done by using the Expr method on the CallContext. 33 func Validate(c *adt.OpContext, b []byte, v cue.Value) (bool, error) { 34 d := NewDecoder("yaml.Validate", b) 35 r := v.Context() 36 for { 37 expr, err := d.Decode() 38 if err != nil { 39 if err == io.EOF { 40 return true, nil 41 } 42 return false, err 43 } 44 45 x := r.BuildExpr(expr) 46 if err := x.Err(); err != nil { 47 return false, err 48 } 49 50 // TODO: consider using subsumption again here. 51 // Alternatives: 52 // - allow definition of non-concrete list, 53 // like list.Of(int), or []int. 54 // - Introduce ! in addition to ?, allowing: 55 // list!: [...] 56 // if err := v.Subsume(inst.Value(), cue.Final()); err != nil { 57 // return false, err 58 // } 59 vx := adt.Unify(c, value.Vertex(x), value.Vertex(v)) 60 if err := x.Err(); err != nil { 61 return false, err 62 } 63 x = value.Make(c, vx) 64 65 if err := x.Validate(cue.Concrete(true)); err != nil { 66 // Strip error codes: incomplete errors are terminal in this case. 67 var b pkg.Bottomer 68 if errors.As(err, &b) { 69 err = b.Bottom().Err 70 } 71 return false, err 72 } 73 } 74 } 75 76 // ValidatePartial validates YAML and confirms it matches the constraints 77 // specified by v using unification. This means that b must be consistent with, 78 // but does not have to be an instance of v. If the YAML source is a stream, 79 // every object must match v. 80 func ValidatePartial(c *adt.OpContext, b []byte, v cue.Value) (bool, error) { 81 d := NewDecoder("yaml.ValidatePartial", b) 82 r := v.Context() 83 for { 84 expr, err := d.Decode() 85 if err != nil { 86 if err == io.EOF { 87 return true, nil 88 } 89 return false, err 90 } 91 92 x := r.BuildExpr(expr) 93 if err := x.Err(); err != nil { 94 return false, err 95 } 96 97 vx := adt.Unify(c, value.Vertex(x), value.Vertex(v)) 98 x = value.Make(c, vx) 99 if err := x.Err(); err != nil { 100 return false, err 101 } 102 } 103 }