Skip to main content

vld/combinators/
custom.rs

1use serde_json::Value;
2use std::marker::PhantomData;
3
4use crate::error::{IssueCode, VldError};
5use crate::schema::VldSchema;
6
7/// Schema from a custom validation function.
8///
9/// Created via [`vld::custom()`](crate::custom).
10///
11/// # Example
12/// ```
13/// use vld::prelude::*;
14///
15/// let even = vld::custom(|v: &serde_json::Value| {
16///     let n = v.as_i64().ok_or("Expected integer")?;
17///     if n % 2 == 0 { Ok(n) } else { Err("Must be even".into()) }
18/// });
19/// assert!(even.parse("4").is_ok());
20/// assert!(even.parse("5").is_err());
21/// ```
22pub struct ZCustom<F, T> {
23    check: F,
24    _marker: PhantomData<T>,
25}
26
27impl<F, T> ZCustom<F, T>
28where
29    F: Fn(&Value) -> Result<T, String>,
30{
31    /// Create the schema (the same as its `vld::` constructor function).
32    pub fn new(check: F) -> Self {
33        Self {
34            check,
35            _marker: PhantomData,
36        }
37    }
38}
39
40impl<F, T> VldSchema for ZCustom<F, T>
41where
42    F: Fn(&Value) -> Result<T, String>,
43{
44    type Output = T;
45
46    fn parse_value(&self, value: &Value) -> Result<T, VldError> {
47        (self.check)(value).map_err(|msg| {
48            VldError::single_with_value(
49                IssueCode::Custom {
50                    code: "custom".to_string(),
51                },
52                msg,
53                value,
54            )
55        })
56    }
57}