h2s_core/
transformable.rs1use crate::functor::ExactlyOne;
2use crate::Error;
3use crate::Never;
4
5pub trait TransformableFrom<T>: Sized {
7 type Error: Error;
8 fn try_transform_from(t: T) -> Result<Self, Self::Error>;
9}
10
11impl<T> TransformableFrom<T> for T {
12 type Error = Never;
13
14 fn try_transform_from(t: T) -> Result<Self, Self::Error> {
15 Ok(t)
16 }
17}
18
19impl<T> TransformableFrom<Vec<T>> for ExactlyOne<T> {
20 type Error = VecToSingleError;
21
22 fn try_transform_from(mut t: Vec<T>) -> Result<Self, Self::Error> {
23 if t.len() > 1 {
24 Err(VecToSingleError::TooManyElements { found: t.len() })
25 } else {
26 t.pop().map(ExactlyOne).ok_or(VecToSingleError::NoElements)
27 }
28 }
29}
30
31impl<N, const A: usize> TransformableFrom<Vec<N>> for [N; A] {
32 type Error = VecToArrayError;
33
34 fn try_transform_from(t: Vec<N>) -> Result<Self, Self::Error> {
35 t.try_into()
36 .map_err(|v: Vec<_>| VecToArrayError::ElementNumberUnmatched {
37 expected: A,
38 found: v.len(),
39 })
40 }
41}
42
43impl<N> TransformableFrom<Vec<N>> for Option<N> {
44 type Error = VecToOptionError;
45
46 fn try_transform_from(mut t: Vec<N>) -> Result<Self, Self::Error> {
47 if t.len() > 1 {
48 Err(Self::Error::TooManyElements { found: t.len() })
49 } else {
50 Ok(t.pop())
51 }
52 }
53}
54
55#[derive(Debug, Clone, Eq, PartialEq)]
56pub enum VecToSingleError {
57 TooManyElements { found: usize },
58 NoElements,
59}
60
61#[derive(Debug, Clone, Eq, PartialEq)]
62pub enum VecToArrayError {
63 ElementNumberUnmatched { expected: usize, found: usize },
64}
65
66#[derive(Debug, Clone, Eq, PartialEq)]
67pub enum VecToOptionError {
68 TooManyElements { found: usize },
69}
70
71#[cfg(test)]
72mod test {
73 use crate::functor::ExactlyOne;
74 use crate::transformable::TransformableFrom;
75 use crate::transformable::{VecToArrayError, VecToOptionError, VecToSingleError};
76
77 #[test]
78 fn identity() {
79 assert_eq!(
80 ExactlyOne::try_transform_from(ExactlyOne(0)),
81 Ok(ExactlyOne(0))
82 );
83 }
84
85 #[test]
86 fn vec_to_single() {
87 assert_eq!(ExactlyOne::try_transform_from(vec![0]), Ok(ExactlyOne(0)));
88 assert_eq!(
89 ExactlyOne::<()>::try_transform_from(vec![]),
90 Err(VecToSingleError::NoElements),
91 );
92 assert_eq!(
93 ExactlyOne::try_transform_from(vec![0, 1]),
94 Err(VecToSingleError::TooManyElements { found: 2 }),
95 );
96 }
97
98 #[test]
99 fn vec_to_array() {
100 assert_eq!(
101 <[_; 2]>::try_transform_from(vec!["foo", "bar"]),
102 Ok(["foo", "bar"])
103 );
104 assert_eq!(
105 <[&str; 3]>::try_transform_from(vec!["foo", "var"]),
106 Err(VecToArrayError::ElementNumberUnmatched {
107 expected: 3,
108 found: 2
109 }),
110 );
111 }
112
113 #[test]
114 fn vec_to_option() {
115 assert_eq!(Option::<()>::try_transform_from(vec![]), Ok(None),);
116 assert_eq!(Option::try_transform_from(vec!["foo"]), Ok(Some("foo")));
117 assert_eq!(
118 Option::try_transform_from(vec!["foo", "var"]),
119 Err(VecToOptionError::TooManyElements { found: 2 })
120 );
121 }
122}