Keats/validator

Can't use custom validator for non-serde types

Opened this issue · 1 comments

xzfc commented

Suppose I want to validate a type from a foreign crate that doesn't implement the Validate nor Serialize traits.
Due to the orphan rule, I can't provide an impl for this type. So instead I have to pass the validator as a function to the attribute #[validate(custom=...)], along with a similar attribute for serde.
However, the generated code requires that T: Serialize and thus fails to build.

Example code:

use foreign::EvenNumber;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use validator::{Validate, ValidationError};

mod foreign {
    #[derive(Debug)]
    pub struct EvenNumber(pub i32);
}

#[derive(Debug, Serialize, Deserialize, Validate)]
struct Struct {
    #[validate(custom = "validate_even_number")]
    #[serde(
        serialize_with = "serialize_even_number",
        deserialize_with = "deserialize_even_number"
    )]
    value: EvenNumber,
}

fn serialize_even_number<S: Serializer>(v: &EvenNumber, ser: S) -> Result<S::Ok, S::Error> {
    v.0.serialize(ser)
}

fn deserialize_even_number<'de, D: Deserializer<'de>>(de: D) -> Result<EvenNumber, D::Error> {
    i32::deserialize(de).map(EvenNumber)
}

fn validate_even_number(v: &EvenNumber) -> Result<(), ValidationError> {
    if v.0 % 2 == 0 {
        Ok(())
    } else {
        Err(ValidationError::new("not even"))
    }
}

fn main() {}
error[E0277]: the trait bound `EvenNumber: Serialize` is not satisfied
  --> src/main.rs:10:41
   |
10 | #[derive(Debug, Serialize, Deserialize, Validate)]
   |                                         ^^^^^^^^ the trait `Serialize` is not implemented for `EvenNumber`
   |
   = help: the following other types implement trait `Serialize`:
             bool
             char
             isize
             i8
             i16
             i32
             i64
             i128
           and 135 others
   = note: required for `&EvenNumber` to implement `Serialize`
note: required by a bound in `ValidationError::add_param`
  --> /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/validator-0.16.1/src/types.rs:20:25
   |
20 |     pub fn add_param<T: Serialize>(&mut self, name: Cow<'static, str>, val: &T) {
   |                         ^^^^^^^^^ required by this bound in `ValidationError::add_param`
   = note: this error originates in the derive macro `Validate` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.

pub fn add_param<T: Serialize>(&mut self, name: Cow<'static, str>, val: &T) {

That will be fixed in the next version or the one after, where we won't pass the value anymore to the errors.