Skip to main content

deke_types/
validator.rs

1use std::{fmt::Debug, sync::Arc};
2
3use crate::{DekeError, DekeResult, SRobotQ};
4
5pub trait Validator<const N: usize>: Sized + Clone + Debug + Send + Sync + 'static {
6    fn validate<E: Into<DekeError>, A: TryInto<SRobotQ<N>, Error = E>>(
7        &mut self,
8        q: A,
9    ) -> DekeResult<()>;
10    fn validate_motion(&mut self, qs: &[SRobotQ<N>]) -> DekeResult<()>;
11}
12
13#[derive(Debug, Clone)]
14pub struct ValidatorAnd<A, B>(pub A, pub B);
15
16#[derive(Debug, Clone)]
17pub struct ValidatorOr<A, B>(pub A, pub B);
18
19#[derive(Debug, Clone)]
20pub struct ValidatorNot<A>(pub A);
21
22impl<const N: usize, A, B> Validator<N> for ValidatorAnd<A, B>
23where
24    A: Validator<N>,
25    B: Validator<N>,
26{
27    #[inline]
28    fn validate<E: Into<DekeError>, Q: TryInto<SRobotQ<N>, Error = E>>(
29        &mut self,
30        q: Q,
31    ) -> DekeResult<()> {
32        let q = q.try_into().map_err(|e| e.into())?;
33        self.0.validate(q)?;
34        self.1.validate(q)
35    }
36
37    #[inline]
38    fn validate_motion(&mut self, qs: &[SRobotQ<N>]) -> DekeResult<()> {
39        self.0.validate_motion(qs)?;
40        self.1.validate_motion(qs)
41    }
42}
43
44impl<const N: usize, A, B> Validator<N> for ValidatorOr<A, B>
45where
46    A: Validator<N>,
47    B: Validator<N>,
48{
49    #[inline]
50    fn validate<E: Into<DekeError>, Q: TryInto<SRobotQ<N>, Error = E>>(
51        &mut self,
52        q: Q,
53    ) -> DekeResult<()> {
54        let q = q.try_into().map_err(|e| e.into())?;
55        match self.0.validate(q) {
56            Ok(()) => Ok(()),
57            Err(_) => self.1.validate(q),
58        }
59    }
60
61    #[inline]
62    fn validate_motion(&mut self, qs: &[SRobotQ<N>]) -> DekeResult<()> {
63        match self.0.validate_motion(qs) {
64            Ok(()) => Ok(()),
65            Err(_) => self.1.validate_motion(qs),
66        }
67    }
68}
69
70impl<const N: usize, A> Validator<N> for ValidatorNot<A>
71where
72    A: Validator<N>,
73{
74    #[inline]
75    fn validate<E: Into<DekeError>, Q: TryInto<SRobotQ<N>, Error = E>>(
76        &mut self,
77        q: Q,
78    ) -> DekeResult<()> {
79        let q = q.try_into().map_err(|e| e.into())?;
80        match self.0.validate(q) {
81            Ok(()) => Err(DekeError::SuperError),
82            Err(_) => Ok(()),
83        }
84    }
85
86    #[inline]
87    fn validate_motion(&mut self, qs: &[SRobotQ<N>]) -> DekeResult<()> {
88        match self.0.validate_motion(qs) {
89            Ok(()) => Err(DekeError::SuperError),
90            Err(_) => Ok(()),
91        }
92    }
93}
94
95#[derive(Clone)]
96pub struct JointValidator<const N: usize> {
97    lower: SRobotQ<N>,
98    upper: SRobotQ<N>,
99    extras: Option<Arc<[Box<dyn Fn(&SRobotQ<N>) -> bool + Send + Sync>]>>,
100}
101
102impl<const N: usize> Debug for JointValidator<N> {
103    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104        f.debug_struct("JointValidator")
105            .field("lower", &self.lower)
106            .field("upper", &self.upper)
107            .field(
108                "extras",
109                &format!(
110                    "[{} extra checks]",
111                    self.extras.as_ref().map(|e| e.len()).unwrap_or(0)
112                ),
113            )
114            .finish()
115    }
116}
117
118impl<const N: usize> JointValidator<N> {
119    pub fn new(lower: SRobotQ<N>, upper: SRobotQ<N>) -> Self {
120        Self {
121            lower,
122            upper,
123            extras: None,
124        }
125    }
126
127    pub fn new_with_extras(
128        lower: SRobotQ<N>,
129        upper: SRobotQ<N>,
130        extras: Vec<Box<dyn Fn(&SRobotQ<N>) -> bool + Send + Sync>>,
131    ) -> Self {
132        Self {
133            lower,
134            upper,
135            extras: Some(extras.into()),
136        }
137    }
138}
139
140impl<const N: usize> Validator<N> for JointValidator<N> {
141    #[inline]
142    fn validate<E: Into<DekeError>, Q: TryInto<SRobotQ<N>, Error = E>>(
143        &mut self,
144        q: Q,
145    ) -> DekeResult<()> {
146        let q = q.try_into().map_err(|e| e.into())?;
147        if q.any_lt(&self.lower) || q.any_gt(&self.upper) {
148            return Err(DekeError::ExceedJointLimits);
149        }
150        if let Some(extras) = &self.extras {
151            for check in extras.iter() {
152                if !check(&q) {
153                    return Err(DekeError::ExceedJointLimits);
154                }
155            }
156        }
157        Ok(())
158    }
159
160    #[inline]
161    fn validate_motion(&mut self, qs: &[SRobotQ<N>]) -> DekeResult<()> {
162        for q in qs {
163            self.validate(*q)?;
164        }
165        Ok(())
166    }
167}