1use crate::stack_str::PackArrayString;
2
3#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
5pub struct DegreeMinutes {
6 pub degrees: i64,
7 pub minutes: f32,
8}
9
10impl From<f32> for DegreeMinutes {
11 fn from(dd: f32) -> Self {
13 let degrees = (dd
14 - match dd % 1.0 >= 0.0 {
15 true => dd % 1.0,
16 false => 1.0 + dd % 1.0,
17 }) as i64;
18 return DegreeMinutes {
19 degrees,
20 minutes: (dd - degrees as f32) * 60.0,
21 };
22 }
23}
24
25impl PackArrayString for DegreeMinutes {
26 fn pack_into<const SIZE: usize>(
27 &self,
28 s: &mut arrayvec::ArrayString<SIZE>,
29 ) -> Result<(), crate::errors::PackError> {
30 s.try_push(('0' as u8 + ((self.degrees / 10) % 10) as u8) as char)?;
32 s.try_push(('0' as u8 + (self.degrees % 10) as u8) as char)?;
33
34 s.try_push(('0' as u8 + ((self.minutes / 10.0) % 10.0) as u8) as char)?;
36 s.try_push(('0' as u8 + (self.minutes % 10.0) as u8) as char)?;
37
38 s.try_push('.')?;
40
41 s.try_push(('0' as u8 + ((self.minutes * 10.0) % 10.0) as u8) as char)?;
43 s.try_push(('0' as u8 + ((self.minutes * 100.0) % 10.0) as u8) as char)?;
44
45 Ok(())
46 }
47}
48
49#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
51pub enum CardinalDirection {
52 North,
53 East,
54 South,
55 West,
56}
57
58impl PackArrayString for CardinalDirection {
59 fn pack_into<const SIZE: usize>(
60 &self,
61 s: &mut arrayvec::ArrayString<SIZE>,
62 ) -> Result<(), crate::errors::PackError> {
63 s.try_push(match self {
64 Self::North => 'N',
65 Self::East => 'E',
66 Self::South => 'S',
67 Self::West => 'W',
68 })?;
69 Ok(())
70 }
71}
72
73pub trait DdmAngle {
75 fn get_direction(&self) -> CardinalDirection;
76 fn get_degree_minutes(&self) -> DegreeMinutes;
77}
78
79#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
81pub struct DdmLatitude {
82 pub ddm: DegreeMinutes,
83 pub direction: CardinalDirection,
84}
85
86impl From<f32> for DdmLatitude {
87 fn from(latitude: f32) -> Self {
88 Self {
89 ddm: match latitude < 0.0 {
90 true => latitude * -1.0,
91 false => latitude,
92 }
93 .into(),
94 direction: match latitude < 0.0 {
95 true => CardinalDirection::South,
96 false => CardinalDirection::North,
97 },
98 }
99 }
100}
101
102impl DdmAngle for DdmLatitude {
103 fn get_direction(&self) -> CardinalDirection {
104 self.direction
105 }
106
107 fn get_degree_minutes(&self) -> DegreeMinutes {
108 self.ddm
109 }
110}
111
112impl PackArrayString for DdmLatitude {
113 fn pack_into<const SIZE: usize>(
114 &self,
115 s: &mut arrayvec::ArrayString<SIZE>,
116 ) -> Result<(), crate::errors::PackError> {
117 self.ddm.pack_into(s)?;
119
120 self.direction.pack_into(s)?;
122
123 Ok(())
124 }
125}
126
127#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
129pub struct DdmLongitude {
130 pub ddm: DegreeMinutes,
131 pub direction: CardinalDirection,
132}
133
134impl From<f32> for DdmLongitude {
135 fn from(longitude: f32) -> Self {
136 Self {
137 ddm: match longitude < 0.0 {
138 true => longitude * -1.0,
139 false => longitude,
140 }
141 .into(),
142 direction: match longitude < 0.0 {
143 true => CardinalDirection::West,
144 false => CardinalDirection::East,
145 },
146 }
147 }
148}
149
150impl DdmAngle for DdmLongitude {
151 fn get_direction(&self) -> CardinalDirection {
152 self.direction
153 }
154
155 fn get_degree_minutes(&self) -> DegreeMinutes {
156 self.ddm
157 }
158}
159
160impl PackArrayString for DdmLongitude {
161 fn pack_into<const SIZE: usize>(
162 &self,
163 s: &mut arrayvec::ArrayString<SIZE>,
164 ) -> Result<(), crate::errors::PackError> {
165 s.try_push(('0' as u8 + (self.ddm.degrees / 100) as u8) as char)?;
167 self.ddm.pack_into(s)?;
168
169 self.direction.pack_into(s)?;
171
172 Ok(())
173 }
174}