this repo has no description
at master 103 lines 2.9 kB view raw
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 15package yaml 16 17import ( 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. 33func 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 x = value.Make(c, vx) 61 if err := x.Err(); err != nil { 62 return false, err 63 } 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. 80func 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}