I am trying to build a library for form validation and of course for learning. Unfortunately, I got stuck on this function pointer signature problem for quite a while. Besides here, I don't know where should I got help on problems related to rust.
Here is a snippet to show the problem I got. There has a struct to represent a field which allow users to pass different functions to validate data during field initiation. To save users' time, I would like to make a few validation functions as default choices. Of course, users should able to override the validation functions if necessary.
Here is the version I would like to make it works:
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
pub struct Errrr{}
struct FakeField<'a, 'd, T>{
pub id: i8,
pub min_len: Option<usize>,
pub validator_lst: Box<[&'a Fn(&Self, &'d Option<T>) -> Result<(), Errrr>]>,
};
pub trait Validate<'d, T> {
fn validate(&self, data: &'d Option<T>) -> Result<(), Errrr>;
};
impl<'a, 'd, T> FakeField<'a, 'd, T>{
fn validate(&self, data: &'d Option<T>) -> Result<(), Errrr> {
for field_validate_fxn in self.validator_lst.as_ref() {
if let Result::Err(err) = field_validate_fxn(&self, data) {
return Result::Err(err);
}
}
Result::Ok(())
}
fn validate_min_len(&self, data: &'d Option<String>) -> Result<(), Errrr> {
if self.min_len.is_none() {
return Result::Ok(());
}
match data.as_ref().map(|s| s.len()).unwrap() {
data_len if data_len < self.min_len.unwrap() => Result::Err(
Errrr{}
),
_ => Result::Ok(()),
}
}
}
impl<'a, 'd, T> Default for FakeField<'a, 'd, T> {
fn default() -> Self {
FakeField {
id: 2,
min_len: Some(1),
// The following line has problem
validator_lst: Box::new([&Self::validate_min_len,])
}
}
}
let _fake_field: FakeField<String> = FakeField{
id: 3,
min_len: None,
..Default::default()
};
}
}
Here is the error:
required for the cast to the object type dyn for<'r> std::ops::Fn(&'r tests::it_works::FakeField<'_, '_, T>, &std::option::Option<T>) -> std::result::Result<(), tests::it_works::Errrr>
Here is the version which works, but not exactly I want:
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
pub struct Errrr{}
struct FakeField<'a, 'd, T>{
pub id: i8,
pub min_len: Option<usize>,
pub validator_lst: Box<[&'a Fn(&Self, &'d Option<T>) -> Result<(), Errrr>]>,
};
pub trait Validate<'d, T> {
fn validate(&self, data: &'d Option<T>) -> Result<(), Errrr>;
};
impl<'a, 'd, T> FakeField<'a, 'd, T>{
fn validate(&self, data: &'d Option<T>) -> Result<(), Errrr> {
for field_validate_fxn in self.validator_lst.as_ref() {
if let Result::Err(err) = field_validate_fxn(&self, data) {
return Result::Err(err);
}
}
Result::Ok(())
}
fn validate_min_len(&self, data: &'d Option<String>) -> Result<(), Errrr> {
if self.min_len.is_none() {
return Result::Ok(());
}
match data.as_ref().map(|s| s.len()).unwrap() {
data_len if data_len < self.min_len.unwrap() => Result::Err(
Errrr{}
),
_ => Result::Ok(()),
}
}
}
impl<'a, 'd, T> Default for FakeField<'a, 'd, T> {
fn default() -> Self {
FakeField {
id: 2,
min_len: Some(1),
// I would like to set a few functions as default validation function
validator_lst: Box::new([])
}
}
}
let _fake_field: FakeField<String> = FakeField{
id: 3,
min_len: None,
..Default::default()
};
}
}
Does anyone have any clues? Thanks a lot.