siderite_validation/
pipeline.rs1use crate::context::ValidationContext;
4use crate::error::{FieldError, LocationItem, ValidationError, ValidationResult};
5use crate::validate::Validate;
6use serde::de::DeserializeOwned;
7use serde_json::{Map, Value};
8
9pub fn parse_value<T>(mut input: Value, mut ctx: ValidationContext) -> ValidationResult<T>
19where
20 T: DeserializeOwned + Validate,
21{
22 T::prepare(&mut input, &mut ctx);
23 if ctx.has_errors() {
24 return Err(ctx.take_errors());
25 }
26 let value: T = match serde_path_to_error::deserialize(input) {
27 Ok(value) => value,
28 Err(err) => {
29 let location = err.path().iter().filter_map(segment_location).collect();
30 let mut error = FieldError::new("invalid", err.inner().to_string());
31 error.location = location;
32 ctx.push(error);
33 return Err(ctx.take_errors());
34 }
35 };
36 value.validate(&mut ctx);
37 if ctx.has_errors() {
38 Err(ctx.take_errors())
39 } else {
40 Ok(value)
41 }
42}
43
44pub fn parse_json<T>(text: &str, ctx: ValidationContext) -> ValidationResult<T>
49where
50 T: DeserializeOwned + Validate,
51{
52 match serde_json::from_str::<Value>(text) {
53 Ok(value) => parse_value(value, ctx),
54 Err(err) => Err(FieldError::new("json_invalid", err.to_string()).into()),
55 }
56}
57
58pub fn validate<T: Validate + ?Sized>(value: &T) -> ValidationResult<()> {
63 let mut ctx = ValidationContext::new();
64 value.validate(&mut ctx);
65 ctx.take_errors().into_result()
66}
67
68fn segment_location(segment: &serde_path_to_error::Segment) -> Option<LocationItem> {
69 use serde_path_to_error::Segment;
70 match segment {
71 Segment::Seq { index } => Some(LocationItem::index(*index)),
72 Segment::Map { key } => Some(LocationItem::key(key.clone())),
73 Segment::Enum { variant } => Some(LocationItem::key(variant.clone())),
74 Segment::Unknown => None,
75 }
76}
77
78pub fn text_pairs_to_value<I, K, V>(pairs: I) -> Value
81where
82 I: IntoIterator<Item = (K, V)>,
83 K: Into<String>,
84 V: Into<String>,
85{
86 let mut map = Map::new();
87 for (key, value) in pairs {
88 let value = Value::String(value.into());
89 match map.entry(key.into()) {
90 serde_json::map::Entry::Vacant(slot) => {
91 slot.insert(value);
92 }
93 serde_json::map::Entry::Occupied(mut slot) => match slot.get_mut() {
94 Value::Array(items) => items.push(value),
95 existing => {
96 let first = existing.take();
97 *existing = Value::Array(vec![first, value]);
98 }
99 },
100 }
101 }
102 Value::Object(map)
103}
104
105pub fn error_value(error: &ValidationError) -> Value {
107 serde_json::to_value(error).unwrap_or(Value::Null)
108}