'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
}
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 |
