1#![deny(unsafe_code, warnings, clippy::all)]
2
3use crate::{Vector3, Vector3Coordinate};
4use thiserror::Error;
5
6impl<T: Vector3Coordinate> From<(T, T, T)> for Vector3<T> {
7 fn from(value: (T, T, T)) -> Self {
8 Vector3 {
9 x: value.0,
10 y: value.1,
11 z: value.2,
12 }
13 }
14}
15
16impl<T: Vector3Coordinate> From<Vector3<T>> for (T, T, T) {
17 fn from(value: Vector3<T>) -> Self {
18 (value.x, value.y, value.z)
19 }
20}
21
22impl<T: Vector3Coordinate> From<[T; 3]> for Vector3<T> {
23 fn from(value: [T; 3]) -> Self {
24 Vector3 {
25 x: value[0],
26 y: value[1],
27 z: value[2],
28 }
29 }
30}
31
32impl<T: Vector3Coordinate> From<Vector3<T>> for [T; 3] {
33 fn from(value: Vector3<T>) -> Self {
34 [value.x, value.y, value.z]
35 }
36}
37
38#[derive(Error, Debug)]
39pub enum ParseVector3Error {
40 #[error("failed to parse numbers")]
41 ParseNumberError(#[from] std::num::ParseFloatError),
42 #[error("invalid format")]
43 InvalidFormat,
44 #[error("invalid Vec<Number>")]
45 InvalidVec,
46}
47
48impl TryFrom<&str> for Vector3<f64> {
49 type Error = ParseVector3Error;
50 fn try_from(value: &str) -> Result<Self, Self::Error> {
51 if value.len() < 14 {
52 return Err(ParseVector3Error::InvalidFormat);
53 }
54
55 if &value[..8] != "Vector3(" || !value.ends_with(')') {
56 return Err(ParseVector3Error::InvalidFormat);
57 }
58
59 let data = &value[8..value.len() - 1];
60 let mut new_vector: [f64; 3] = [0.0, 0.0, 0.0];
61 for (index, coord) in data.split(',').enumerate() {
62 new_vector[index] = coord.trim().parse::<f64>()?;
63 }
64
65 Ok(Vector3::from(new_vector))
66 }
67}
68
69impl<T: Vector3Coordinate> TryFrom<Vec<T>> for Vector3<T> {
70 type Error = ParseVector3Error;
71 fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
72 let x = value.first().ok_or(ParseVector3Error::InvalidVec)?;
73 let y = value.get(1).ok_or(ParseVector3Error::InvalidVec)?;
74 let z = value.get(2).ok_or(ParseVector3Error::InvalidVec)?;
75
76 Ok(Vector3::new(*x, *y, *z))
77 }
78}