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    pub fn new(check: F) -> Self {
32        Self {
33            check,
34            _marker: PhantomData,
35        }
36    }
37}
38
39impl<F, T> VldSchema for ZCustom<F, T>
40where
41    F: Fn(&Value) -> Result<T, String>,
42{
43    type Output = T;
44
45    fn parse_value(&self, value: &Value) -> Result<T, VldError> {
46        (self.check)(value).map_err(|msg| {
47            VldError::single_with_value(
48                IssueCode::Custom {
49                    code: "custom".to_string(),
50                },
51                msg,
52                value,
53            )
54        })
55    }
56}