1use piper_can::PiperFrame;
6use smallvec::SmallVec;
7
8#[cfg(test)]
11const _: () = {
12 fn assert_copy<T: Copy>() {}
13 fn check() {
14 assert_copy::<piper_can::PiperFrame>();
15 }
16 let _ = check;
18};
19
20pub type FrameBuffer = SmallVec<[PiperFrame; 6]>;
41
42#[derive(Debug, Clone)]
49pub struct RealtimeCommand {
50 frames: FrameBuffer,
51}
52
53impl RealtimeCommand {
54 #[inline]
58 pub fn single(frame: PiperFrame) -> Self {
59 let mut buffer = FrameBuffer::new();
60 buffer.push(frame); RealtimeCommand { frames: buffer }
62 }
63
64 #[inline]
72 pub fn package(frames: impl IntoIterator<Item = PiperFrame>) -> Self {
73 let buffer: FrameBuffer = frames.into_iter().collect();
74 RealtimeCommand { frames: buffer }
75 }
76
77 #[inline]
79 pub fn len(&self) -> usize {
80 self.frames.len()
81 }
82
83 #[inline]
85 pub fn is_empty(&self) -> bool {
86 self.frames.is_empty()
87 }
88
89 #[inline]
91 pub fn iter(&self) -> impl Iterator<Item = &PiperFrame> {
92 self.frames.iter()
93 }
94
95 #[inline]
97 pub fn into_frames(self) -> FrameBuffer {
98 self.frames
99 }
100}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
106pub enum CommandPriority {
107 RealtimeControl,
113
114 ReliableCommand,
120}
121
122#[derive(Debug, Clone, Copy)]
126pub struct PiperCommand {
127 pub frame: PiperFrame,
129 pub priority: CommandPriority,
131}
132
133impl PiperCommand {
134 pub fn realtime(frame: PiperFrame) -> Self {
136 Self {
137 frame,
138 priority: CommandPriority::RealtimeControl,
139 }
140 }
141
142 pub fn reliable(frame: PiperFrame) -> Self {
144 Self {
145 frame,
146 priority: CommandPriority::ReliableCommand,
147 }
148 }
149
150 pub fn frame(&self) -> PiperFrame {
152 self.frame
153 }
154
155 pub fn priority(&self) -> CommandPriority {
157 self.priority
158 }
159}
160
161impl From<PiperFrame> for PiperCommand {
162 fn from(frame: PiperFrame) -> Self {
164 Self::reliable(frame)
165 }
166}
167
168impl From<PiperCommand> for PiperFrame {
169 fn from(cmd: PiperCommand) -> Self {
170 cmd.frame
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn test_command_priority() {
180 let frame = PiperFrame::new_standard(0x123, &[1, 2, 3]);
181
182 let realtime_cmd = PiperCommand::realtime(frame);
183 assert_eq!(realtime_cmd.priority(), CommandPriority::RealtimeControl);
184
185 let reliable_cmd = PiperCommand::reliable(frame);
186 assert_eq!(reliable_cmd.priority(), CommandPriority::ReliableCommand);
187 }
188
189 #[test]
190 fn test_command_from_frame() {
191 let frame = PiperFrame::new_standard(0x123, &[1, 2, 3]);
192 let cmd: PiperCommand = frame.into();
193
194 assert_eq!(cmd.priority(), CommandPriority::ReliableCommand);
196 assert_eq!(cmd.frame().id, 0x123);
197 }
198
199 #[test]
200 fn test_command_to_frame() {
201 let frame = PiperFrame::new_standard(0x123, &[1, 2, 3]);
202 let cmd = PiperCommand::realtime(frame);
203
204 let converted_frame: PiperFrame = cmd.into();
205 assert_eq!(converted_frame.id, 0x123);
206 }
207}
208
209#[cfg(test)]
210mod realtime_command_tests {
211 use super::*;
212
213 #[test]
214 fn test_realtime_command_single() {
215 let frame = PiperFrame::new_standard(0x123, &[0x01, 0x02]);
216 let cmd = RealtimeCommand::single(frame);
217 assert_eq!(cmd.len(), 1);
218 assert!(!cmd.is_empty());
219 }
220
221 #[test]
222 fn test_realtime_command_package() {
223 let frames = [
224 PiperFrame::new_standard(0x155, &[0x01]),
225 PiperFrame::new_standard(0x156, &[0x02]),
226 PiperFrame::new_standard(0x157, &[0x03]),
227 ];
228 let cmd = RealtimeCommand::package(frames);
229 assert_eq!(cmd.len(), 3);
230 assert!(!cmd.is_empty());
231 }
232
233 #[test]
234 fn test_realtime_command_empty() {
235 let frames: [PiperFrame; 0] = [];
236 let cmd = RealtimeCommand::package(frames);
237 assert_eq!(cmd.len(), 0);
238 assert!(cmd.is_empty());
239 }
240
241 #[test]
242 fn test_realtime_command_iter() {
243 let frames = [
244 PiperFrame::new_standard(0x155, &[0x01]),
245 PiperFrame::new_standard(0x156, &[0x02]),
246 ];
247 let cmd = RealtimeCommand::package(frames);
248 let collected: Vec<_> = cmd.iter().collect();
249 assert_eq!(collected.len(), 2);
250 }
251
252 #[test]
253 fn test_realtime_command_into_frames() {
254 let frames = [
255 PiperFrame::new_standard(0x155, &[0x01]),
256 PiperFrame::new_standard(0x156, &[0x02]),
257 ];
258 let cmd = RealtimeCommand::package(frames);
259 let buffer = cmd.into_frames();
260 assert_eq!(buffer.len(), 2);
261 }
262}