Skip to main content

vec3_rs/
convert.rs

1use crate::{Vector3, Vector3Coordinate};
2use thiserror::Error;
3
4impl<T: Vector3Coordinate> From<(T, T, T)> for Vector3<T> {
5    fn from(value: (T, T, T)) -> Self {
6        Self {
7            x: value.0,
8            y: value.1,
9            z: value.2,
10        }
11    }
12}
13
14impl<T: Vector3Coordinate> From<Vector3<T>> for (T, T, T) {
15    fn from(value: Vector3<T>) -> Self {
16        (value.x, value.y, value.z)
17    }
18}
19
20impl<T: Vector3Coordinate> From<[T; 3]> for Vector3<T> {
21    fn from(value: [T; 3]) -> Self {
22        let [x, y, z] = value;
23        Self { x, y, z }
24    }
25}
26
27#[cfg(feature = "std")]
28impl<T: Vector3Coordinate> From<Vector3<T>> for [T; 3] {
29    fn from(value: Vector3<T>) -> Self {
30        [value.x, value.y, value.z]
31    }
32}
33
34#[derive(Error, Debug)]
35pub enum ParseVector3Error {
36    #[error("failed to parse #{0}th component")]
37    StringParseComponentError(usize),
38    #[error("invalid format")]
39    InvalidStringFormat,
40    #[error("invalid vector length: expected 3, got {0}")]
41    InvalidVec(usize),
42}
43
44#[cfg(feature = "std")]
45impl<T: Vector3Coordinate> TryFrom<Vec<T>> for Vector3<T> {
46    type Error = ParseVector3Error;
47    fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
48        let array: [T; 3] = value
49            .try_into()
50            .map_err(|v: Vec<T>| ParseVector3Error::InvalidVec(v.len()))?;
51        Ok(Self::from(array))
52    }
53}
54
55#[cfg(feature = "std")]
56impl<T: Vector3Coordinate> TryFrom<std::collections::VecDeque<T>> for Vector3<T> {
57    type Error = ParseVector3Error;
58    fn try_from(mut value: std::collections::VecDeque<T>) -> Result<Self, Self::Error> {
59        let x = value
60            .pop_front()
61            .ok_or(ParseVector3Error::InvalidVec(value.len()))?;
62        let y = value
63            .pop_front()
64            .ok_or(ParseVector3Error::InvalidVec(value.len()))?;
65        let z = value
66            .pop_front()
67            .ok_or(ParseVector3Error::InvalidVec(value.len()))?;
68        Ok(Self::new(x, y, z))
69    }
70}
71
72impl<T> core::str::FromStr for Vector3<T>
73where
74    T: Vector3Coordinate + core::str::FromStr,
75{
76    type Err = ParseVector3Error;
77    fn from_str(s: &str) -> Result<Self, Self::Err> {
78        let Some(data) = s.strip_prefix("Vector3(") else {
79            return Err(ParseVector3Error::InvalidStringFormat);
80        };
81        let Some(data) = data.strip_suffix(")") else {
82            return Err(ParseVector3Error::InvalidStringFormat);
83        };
84
85        let mut components = data
86            .split(',')
87            .take(3)
88            .enumerate()
89            .flat_map(|(index, coord)| {
90                coord
91                    .trim()
92                    .parse::<T>()
93                    .map_err(|_| ParseVector3Error::StringParseComponentError(index + 1))
94            });
95
96        // dear rust, collect into array/tuple when?
97        // do i seriously need to pull itertools for this??
98        let x = components
99            .next()
100            .ok_or(ParseVector3Error::StringParseComponentError(1))?;
101        let y = components
102            .next()
103            .ok_or(ParseVector3Error::StringParseComponentError(2))?;
104        let z = components
105            .next()
106            .ok_or(ParseVector3Error::StringParseComponentError(3))?;
107
108        Ok(Self::new(x, y, z))
109    }
110}
111
112#[cfg(test)]
113mod test {
114    use super::*;
115
116    #[test]
117    fn vec_string() {
118        let v1: Vector3<i32> = Vector3::new(1, 2, 3);
119        let v2: Vector3<i32> = String::from("Vector3( 1,2,     3)").parse().unwrap();
120        assert_eq!(v1, v2);
121    }
122
123    #[test]
124    fn vec_str() {
125        let v1 = Vector3::new(1, 2, 3);
126        let v2 = "Vector3(1,  2 ,3 )".parse().unwrap();
127        assert_eq!(v1, v2);
128    }
129
130    #[test]
131    fn vec_tuple() {
132        let v1 = Vector3::new(1, 2, 3);
133        let v2 = (1, 2, 3).into();
134        assert_eq!(v1, v2);
135    }
136
137    #[test]
138    fn vec_array() {
139        let v1 = Vector3::new(1, 2, 3);
140        let v2 = [1, 2, 3].into();
141        assert_eq!(v1, v2);
142    }
143
144    #[test]
145    fn vec_vec() {
146        let v1 = Vector3::new(1, 2, 3);
147        let v2 = vec![1, 2, 3].try_into().unwrap();
148        assert_eq!(v1, v2);
149    }
150
151    #[test]
152    fn vec_deq() {
153        let v1 = Vector3::new(1, 2, 3);
154        let v2 = std::collections::VecDeque::from([1, 2, 3])
155            .try_into()
156            .unwrap();
157        assert_eq!(v1, v2);
158    }
159}