package definition import ( "bytes" "encoding/json" "git.yuntuo.hk/k2safe/orbit/internal/jsonvalue" ) // ValidateData 在实例输入、任务成功结果、信号和块输出边界复用同一类型契约。 // 使用精确JSON数值文本;大小、重复字段、Unicode和嵌套限制先于类型检查。 func ValidateData(schema Type, raw json.RawMessage) error { if err := checkType(schema, 0); err != nil { return err } if len(raw) == 0 || len(raw) > 256<<10 { return invalid("data", "JSON value required, maximum 256 KiB") } if _, err := jsonvalue.Canonical(raw); err != nil { return invalid("data", "invalid JSON, duplicate fields or unsupported value limits") } var value any d := json.NewDecoder(bytes.NewReader(raw)) d.UseNumber() if err := d.Decode(&value); err != nil { return invalid("data", "invalid JSON value") } return matchData(schema, value) } func matchData(schema Type, value any) error { valid := false switch schema.Kind { case "JSON": return nil case "NULL": valid = value == nil case "STRING": v, ok := value.(string) valid = ok && (len(schema.Enum) == 0 || contains(schema.Enum, v)) case "NUMBER": _, valid = value.(json.Number) case "BOOLEAN": _, valid = value.(bool) case "OBJECT": v, ok := value.(map[string]any) if !ok || len(v) != len(schema.Fields) { return invalid("data", "object fields do not match declared type") } for key, t := range schema.Fields { child, ok := v[key] if !ok { return invalid("data", "required object field missing") } if err := matchData(t, child); err != nil { return err } } return nil case "ARRAY": v, ok := value.([]any) if !ok || len(v) > 4096 { return invalid("data", "array required, maximum 4096 elements") } for _, child := range v { if err := matchData(*schema.Items, child); err != nil { return err } } return nil } if !valid { return invalid("data", "value does not match declared type") } return nil }