'how to access value with Get trait

I believe this is a basic rust question, however, I am quite new to rust. The issue is in the following validate method implemented for X in the below test , I am trying to modify and pass the hardcoded value '10' to the method (not as function parameter ). I was told that I can acheive this with the Get trait found here https://docs.substrate.io/rustdocs/latest/frame_support/traits/trait.Get.html, however I do need an example on how to implement the Get trait to achieve this . From the test below, the call stack begins from decode, which then calls validate , I am trying to modify this code to access 10 using the Get trait how do I achieve this ? can a sample implementation be provided or some clear guidance

#[cfg(test)]
mod test {
    #[derive(Debug, Eq, PartialEq)]
    struct ValidARange;
 
    type CheckARange = (ValidARange, QED);

    #[derive(Debug, Eq, PartialEq, codec::Encode, codec::Decode)]
    struct X {
        a: u32,
        b: u32,
    }

    impl Validate<ValidARange> for X {
        fn validate(self) -> Result<X, &'static str> {
            if self.a > 10 {
                Err("Out of range")
            } else {
                Ok(self)
            }
        }
    }

    #[test]
    fn test_valid_a() {
        let valid = X { a: 10, b: 0xCAFEBABE };
        let bytes = valid.encode();
        assert_eq!(
            Ok(Validated { value: valid, _marker: PhantomData }),
            Validated::<X, CheckARange>::decode(&mut &bytes[..])
        );
    }
}


 below are deficitions for traits and structs used

#[derive(Default, Copy, Clone, PartialEq, Eq, Debug, TypeInfo)]
pub struct Validated<T, U> {
    value: T,
    _marker: PhantomData<U>,
}
pub trait Validate<U>: Sized {
    fn validate(self) -> Result<Self, &'static str>;
}

impl<T: Validate<U> + Validate<V>, U, V> Validate<(U, V)> for T {

    fn validate(self) -> Result<Self, &'static str> {
        let value = Validate::<U>::validate(self)?;
        let value = Validate::<V>::validate(value)?;
        Ok(value)
    }
}

impl<T: codec::Decode + Validate<(U, V)>, U, V> codec::Decode for Validated<T, (U, V)> {
    fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
        let value = Validate::validate(T::decode(input)?).map_err(Into::<codec::Error>::into)?;
        Ok(Validated { value, _marker: PhantomData })
    }
}


Solution 1:[1]

Using Get the "10" value is still hardcoded in a bunch of places in types with this approach (as I mentioned in the comment).

I took a freedom to simplify a bit, but kept the essentials.

Using u32 instead of your X it looks like this:

pub trait Get<T> {
    fn get() -> T;
}

struct ValidInRange0to10;
struct ValidInRange0to42;

impl Get<u32> for ValidInRange0to10 {
    fn get() -> u32 { 10 }
}

impl Get<u32> for ValidInRange0to42 {
    fn get() -> u32 { 42 }
}

pub trait Validate<U>: Sized {
    fn validate(self) -> bool;
}

impl<U: Get<u32>> Validate<U> for u32 {
    fn validate(self) -> bool {
        self <= U::get()
    }
}

fn main() {
    println!("{}", Validate::<ValidInRange0to10>::validate(5));  // true
    println!("{}", Validate::<ValidInRange0to10>::validate(15)); // false
    println!("{}", Validate::<ValidInRange0to42>::validate(15)); // true
    println!("{}", Validate::<ValidInRange0to42>::validate(43)); // false
}

playground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 battlmonstr