Is there a way to write a generic function that returns the len

Consider that I want to write a series of validations. I use Chain of responsibility design pattern.
so i write trait like

use crate::error::ValidationError;

/// This trait tries to create a set of rules for data validation
/// by implementing the chain of responsibility model.
pub trait Ruled<T> {
    /// This method checks the validation rules.
    /// If success return (), otherwise returns one of validation error.
    fn handle(&mut self, value: &T) -> Result<(), ValidationError>;

    /// This method specifies the next rule.
    fn chain(&mut self, rule: Box<dyn Ruled<T>>);

    /// This method refers to the next rule.
    /// If success return next rule, otherwise return None.
    fn next(&mut self) -> &mut Option<Box<dyn Ruled<T>>>;

    /// This method performs validation for each rule.
    /// If success return (), otherwise return None.
    fn execute(&mut self, value: &T) -> Result<(), ValidationError> {
        self.handle(value)?;

        if let Some(next) = &mut self.next() {
            next.execute(value)?;
        }

        Ok(())
    }
}

And for example I implement extremum like this

use crate::{error::ValidationError, rule::Ruled};

/// Validates the minimum and maximum allowed value for each numeric type.
pub struct Extremum<T> {
    min: Option<T>,
    max: Option<T>,
    next: Option<Box<dyn Ruled<T>>>,
}

impl<T> Extremum<T> {
    pub fn min(&mut self, value: T) {
        self.min = Some(value);
    }

    pub fn max(&mut self, value: T) {
        self.max = Some(value);
    }
}

impl<T> Default for Extremum<T> {
    fn default() -> Self {
        Self {
            min: None,
            max: None,
            next: None,
        }
    }
}

impl<T> Ruled<T> for Extremum<T>
where
    T: Ord + Eq + std::fmt::Display,
{
    /// Validate the minimum and/or maximum allowed value.
    ///
    /// ```
    /// use validation::rule::{Extremum, Ruled};
    ///
    /// let mut extremum = Extremum::<u64>::default();
    /// extremum.min(10);
    /// extremum.max(100);
    ///
    /// let result = extremum.handle(&70);
    /// assert_eq!(result, Ok(()));
    /// ```
    fn handle(&mut self, value: &T) -> Result<(), ValidationError> {
        match (self.min.as_ref(), self.max.as_ref()) {
            (Some(min), _) if value.lt(min) => Err(ValidationError::MinExceeded),
            (_, Some(max)) if value.gt(max) => Err(ValidationError::MaxExceeded),
            (None, None) => Err(ValidationError::MinMaxNotDefined),
            _ => Ok(()),
        }
    }

    /// This method specifies the next rule.
    fn chain(&mut self, rule: Box<dyn Ruled<T>>) {
        self.next = Some(rule);
    }

    /// This method refers to the next rule.
    fn next(&mut self) -> &mut Option<Box<dyn Ruled<T>>> {
        &mut self.next
    }
}

But what I do not understand. How can I write a generic function that returns the length?
for example I want length on Vectors, Array, Tuples, String data type and of course String types should return chars().count().

use crate::{error::ValidationError, rule::Ruled};

pub struct Length<T> {
    size: Option<usize>,
    next: Option<Box<dyn Ruled<T>>>,
}

impl<T> Length<T> {
    pub fn size(&mut self, value: usize) {
        self.size = Some(value);
    }
}

impl<T> Default for Length<T> {
    fn default() -> Self {
        Self { size: None, next: None }
    }
}

impl<T> Ruled<T> for Length<T> {
    fn handle(&mut self, value: &T) -> Result<(), ValidationError> {
        /// todo how to write 
        Ok(())
    }

    /// This method specifies the next rule.
    fn chain(&mut self, rule: Box<dyn Ruled<T>>) {
        self.next = Some(rule);
    }

    /// This method refers to the next rule.
    fn next(&mut self) -> &mut Option<Box<dyn Ruled<T>>> {
        &mut self.next
    }
}

You'll have to define a trait including a method that returns the length, and implement it for all the relevant types yourself.

That's not so "of course", not at all. It could be at least any one of:

  • the number of bytes (which is .len() for Rust strings);
  • the number of code units (which is not the same as the number of bytes for UCS-2, UCS-4, UTF-16, and UTF-32);
  • the number of code points (which is .chars().count()); or
  • the number of grapheme clusters (which is unicode_segmentation::grapheme_clusters(s, true).count()).
4 Likes

Let's assume for a moment that we leave the string data type aside.
Can such a thing be done for the length of the string?

fn longer_exact_size_iterator<T, U>(x: T, y: T) -> T
where T: IntoIterator<IntoIter=U> + Copy,
    U: ExactSizeIterator,
{
    if x.into_iter().len() > y.into_iter().len() {
        x
    } else {
        y
    }
}

I'm new to Rust programming language and I'm learning, I'd appreciate it if you could explain a bit more

The question is, what is the length of the string? There are several possible answers, and no one of them is absolutely preferred to others.

Yes, you are right. But as I said, it is assumed that the length of the string is the number of bytes. Is there still a general solution as I mentioned above or not?
I am new and would like to learn more. Therefore, thank you for explaining more so that I can learn.
I found the above function from this address

The function that you presented above compiles and is correct as long as you define the length of a value to be the number of items in its IntoIterator impl.

You can also drop the ExactSizeIterator bound and use .count() instead of .len(). This will mean that it will no longer always be O(1), but it will work for a wider range of types.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.