off_rs/geometry/
position.rs1use std::fmt::{Debug, Display, Formatter};
2
3#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub enum Error {
6 FromF32(String),
7}
8
9impl Display for Error {
10 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
11 match self {
12 Self::FromF32(msg) => write!(f, "Failed to convert `f32` to `Position`: {}", msg),
13 }
14 }
15}
16
17impl std::error::Error for Error {}
18
19#[derive(Copy, Clone, PartialEq, Debug, Default)]
22pub struct Position {
23 pub x: f32,
25 pub y: f32,
27 pub z: f32,
29}
30
31impl Position {
32 #[must_use]
34 pub fn new(x: f32, y: f32, z: f32) -> Self {
35 Self { x, y, z }
36 }
37}
38
39impl From<Position> for Vec<f32> {
40 fn from(value: Position) -> Vec<f32> {
42 vec![value.x, value.y, value.z]
43 }
44}
45
46impl TryFrom<Vec<f32>> for Position {
47 type Error = Error;
48
49 fn try_from(value: Vec<f32>) -> std::result::Result<Self, Self::Error> {
51 if value.len() != 3 {
52 return Err(Self::Error::FromF32(format!(
53 "Invalid amount of arguments (expected: 3, actual: {})",
54 value.len()
55 )));
56 }
57
58 Ok(Self {
59 x: value[0],
60 y: value[1],
61 z: value[2],
62 })
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 #[allow(clippy::float_cmp)]
72 fn position() {
73 let pos = Position::new(1.0, 2.0, 3.0);
74 assert_eq!(pos.x, 1.0,);
75 assert_eq!(pos.y, 2.0);
76 assert_eq!(pos.z, 3.0);
77 }
78
79 #[test]
80 fn position_from() {
81 let pos = Position::new(1.0, 2.0, 3.0);
82 assert_eq!(Vec::from(pos), vec![1.0, 2.0, 3.0]);
83 }
84
85 #[test]
86 fn try_from_positiom() {
87 let vec = vec![1.0, 2.0, 3.0];
88 let position = Position::try_from(vec);
89 assert!(position.is_ok());
90 assert_eq!(position.unwrap(), Position::new(1.0, 2.0, 3.0));
91 }
92
93 #[test]
94 fn try_from_positiom_too_little_arguments() {
95 let vec = vec![1.0, 2.0];
96 let position = Position::try_from(vec);
97 assert!(position.is_err());
98 assert!(matches!(position.unwrap_err(), Error::FromF32(_)));
99 }
100
101 #[test]
102 fn try_from_positiom_too_many_arguments() {
103 let vec = vec![1.0, 2.0, 3.0, 4.0];
104 let position = Position::try_from(vec);
105 assert!(position.is_err());
106 assert!(matches!(position.unwrap_err(), Error::FromF32(_)));
107 }
108}