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