1use std::{convert::TryInto, io::Write};
6
7use cameleon_impl::bytes_io::WriteBytes;
8
9use crate::u3v::{Error, Result};
10
11#[derive(Debug)]
12pub struct CommandPacket<T> {
13 ccd: CommandCcd,
14 scd: T,
15}
16
17impl<T> CommandPacket<T>
18where
19 T: CommandScd,
20{
21 const PREFIX_MAGIC: u32 = 0x4356_3355;
22
23 const ACK_HEADER_LENGTH: usize = 4 + 8;
25
26 const MINIMUM_ACK_SCD_LENGTH: u16 = 4;
28
29 pub fn serialize(&self, mut buf: impl Write) -> Result<()> {
30 buf.write_bytes_le(Self::PREFIX_MAGIC)?;
31 self.ccd.serialize(&mut buf)?;
32 self.scd.serialize(&mut buf)?;
33
34 Ok(())
35 }
36
37 pub fn ccd(&self) -> &CommandCcd {
38 &self.ccd
39 }
40
41 pub fn scd(&self) -> &T {
42 &self.scd
43 }
44
45 pub fn cmd_len(&self) -> usize {
46 4 + CommandCcd::len() as usize + self.scd.scd_len() as usize
48 }
49
50 pub fn request_id(&self) -> u16 {
51 self.ccd.request_id
52 }
53
54 pub fn maximum_ack_len(&self) -> usize {
56 let scd_len = self.scd.ack_scd_len();
57 let maximum_scd_length = std::cmp::max(scd_len, Self::MINIMUM_ACK_SCD_LENGTH) as usize;
58
59 Self::ACK_HEADER_LENGTH + maximum_scd_length
60 }
61
62 pub fn new(scd: T, request_id: u16) -> Self {
63 let ccd = CommandCcd::from_scd(&scd, request_id);
64 Self { ccd, scd }
65 }
66
67 fn header_len() -> usize {
68 4 + CommandCcd::len() as usize
69 }
70}
71
72#[derive(Clone, Debug, PartialEq, Eq)]
73pub struct ReadMem {
74 pub(crate) address: u64,
75 pub(crate) read_length: u16,
76}
77
78pub struct ReadMemChunks {
79 address: u64,
80 read_length: u16,
81 maximum_read_length: usize,
82}
83
84impl std::iter::Iterator for ReadMemChunks {
85 type Item = ReadMem;
86
87 fn next(&mut self) -> Option<ReadMem> {
88 if self.read_length == 0 {
89 return None;
90 }
91
92 if self.read_length as usize > self.maximum_read_length {
93 let next_item = ReadMem::new(self.address, self.maximum_read_length as u16);
94 self.read_length -= self.maximum_read_length as u16;
95 self.address += self.maximum_read_length as u64;
96 Some(next_item)
97 } else {
98 let next_item = ReadMem::new(self.address, self.read_length);
99 self.read_length = 0;
100 Some(next_item)
101 }
102 }
103}
104
105impl ReadMem {
106 #[must_use]
107 pub fn new(address: u64, read_length: u16) -> Self {
108 Self {
109 address,
110 read_length,
111 }
112 }
113
114 pub fn chunks(&self, ack_len: usize) -> Result<ReadMemChunks> {
116 let ack_header_length = CommandPacket::<ReadMem>::ACK_HEADER_LENGTH;
117 if ack_len <= ack_header_length {
118 let msg = format!(
119 "ack length must be larger than {}",
120 CommandPacket::<ReadMem>::ACK_HEADER_LENGTH
121 );
122 return Err(Error::InvalidPacket(msg.into()));
123 };
124 let maximum_read_length = ack_len - ack_header_length;
125
126 Ok(ReadMemChunks {
127 address: self.address,
128 read_length: self.read_length,
129 maximum_read_length,
130 })
131 }
132
133 pub fn maximum_read_length(maximum_ack_len: usize) -> u16 {
135 (maximum_ack_len - CommandPacket::<ReadMem>::ACK_HEADER_LENGTH)
136 .try_into()
137 .unwrap_or(u16::MAX)
138 }
139
140 #[must_use]
141 pub fn read_length(&self) -> u16 {
142 self.read_length
143 }
144}
145
146#[derive(Clone, Debug, PartialEq, Eq)]
147pub struct WriteMem<'a> {
148 pub(crate) address: u64,
149 pub(crate) data: &'a [u8],
150 data_len: u16,
151 len: u16,
152}
153
154pub struct WriteMemChunks<'a> {
155 address: u64,
156 data: &'a [u8],
157 data_idx: usize,
158 maximum_data_len: usize,
159}
160
161impl<'a> std::iter::Iterator for WriteMemChunks<'a> {
162 type Item = WriteMem<'a>;
163
164 fn next(&mut self) -> Option<Self::Item> {
165 if self.data_idx == self.data.len() {
166 return None;
167 }
168
169 if self.data_idx + self.maximum_data_len < self.data.len() {
170 let next_item = WriteMem::new(
171 self.address,
172 &self.data[self.data_idx..self.data_idx + self.maximum_data_len],
173 )
174 .unwrap();
175 self.address += self.maximum_data_len as u64;
176 self.data_idx += self.maximum_data_len;
177 Some(next_item)
178 } else {
179 let next_item = WriteMem::new(self.address, &self.data[self.data_idx..]).unwrap();
180 self.data_idx = self.data.len();
181 Some(next_item)
182 }
183 }
184}
185
186impl<'a> WriteMem<'a> {
187 pub fn new(address: u64, data: &'a [u8]) -> Result<Self> {
188 let data_len = into_scd_len(data.len())?;
189 let len = into_scd_len(data.len() + 8)?;
190
191 Ok(Self {
192 address,
193 data,
194 data_len,
195 len,
196 })
197 }
198
199 #[must_use]
201 pub fn data_len(&self) -> usize {
202 self.data.len()
203 }
204
205 pub fn chunks(&self, cmd_len: usize) -> Result<WriteMemChunks<'a>> {
207 let cmd_header_len = CommandPacket::<WriteMem>::header_len() + 8;
208 if cmd_len <= cmd_header_len {
209 let msg = format!(
210 "cmd_len must be larger than {}",
211 CommandPacket::<WriteMem>::header_len() + 8
212 );
213 return Err(Error::InvalidPacket(msg.into()));
214 };
215 let maximum_data_len = cmd_len - cmd_header_len;
216
217 Ok(WriteMemChunks {
218 address: self.address,
219 data: self.data,
220 data_idx: 0,
221 maximum_data_len,
222 })
223 }
224}
225
226#[derive(Clone, Debug, PartialEq, Eq)]
227pub struct ReadMemStacked {
228 pub(crate) entries: Vec<ReadMem>,
229 len: u16,
230 ack_scd_len: u16,
231}
232
233impl ReadMemStacked {
234 pub fn new(entries: Vec<ReadMem>) -> Result<Self> {
235 let len = Self::len(&entries)?;
236 let ack_scd_len = Self::ack_scd_len(&entries)?;
237
238 Ok(Self {
239 entries,
240 len,
241 ack_scd_len,
242 })
243 }
244
245 fn len(regs: &[ReadMem]) -> Result<u16> {
246 let len = regs.iter().fold(0, |acc, reg| acc + reg.scd_len() as usize);
247 into_scd_len(len)
248 }
249
250 fn ack_scd_len(entries: &[ReadMem]) -> Result<u16> {
251 let mut acc: u16 = 0;
252 for ent in entries {
253 acc = acc.checked_add(ent.read_length).ok_or_else(|| {
254 Error::InvalidPacket("total read length must be less than u16::MAX".into())
255 })?;
256 }
257
258 Ok(acc)
259 }
260}
261
262#[derive(Clone, Debug, PartialEq, Eq)]
263pub struct WriteMemStacked<'a> {
264 pub(crate) entries: Vec<WriteMem<'a>>,
265 len: u16,
266 ack_scd_len: u16,
267}
268
269impl<'a> WriteMemStacked<'a> {
270 pub fn new(entries: Vec<WriteMem<'a>>) -> Result<Self> {
271 let len = Self::len(&entries)?;
272 let ack_scd_len = entries.len() as u16 * 4;
273 Ok(Self {
274 entries,
275 len,
276 ack_scd_len,
277 })
278 }
279
280 fn len(entries: &[WriteMem<'a>]) -> Result<u16> {
281 let len = entries
282 .iter()
283 .fold(0, |acc, cmd| acc + 12 + cmd.data_len as usize);
284 into_scd_len(len)
285 }
286}
287
288#[derive(Clone, Debug, PartialEq, Eq)]
289pub struct CommandCcd {
290 flag: CommandFlag,
291 scd_kind: ScdKind,
292 scd_len: u16,
293 request_id: u16,
294}
295
296impl CommandCcd {
297 #[must_use]
298 pub fn flag(&self) -> CommandFlag {
299 self.flag
300 }
301
302 #[must_use]
303 pub fn scd_kind(&self) -> ScdKind {
304 self.scd_kind
305 }
306
307 #[must_use]
308 pub fn scd_len(&self) -> u16 {
309 self.scd_len
310 }
311
312 #[must_use]
313 pub fn request_id(&self) -> u16 {
314 self.request_id
315 }
316
317 pub(crate) fn new(flag: CommandFlag, scd_kind: ScdKind, scd_len: u16, request_id: u16) -> Self {
318 Self {
319 flag,
320 scd_kind,
321 scd_len,
322 request_id,
323 }
324 }
325
326 fn from_scd(scd: &impl CommandScd, request_id: u16) -> Self {
327 Self::new(scd.flag(), scd.scd_kind(), scd.scd_len(), request_id)
328 }
329
330 fn serialize(&self, mut buf: impl Write) -> Result<()> {
331 self.flag.serialize(&mut buf)?;
332 self.scd_kind.serialize(&mut buf)?;
333 buf.write_bytes_le(self.scd_len)?;
334
335 buf.write_bytes_le(self.request_id)?;
336 Ok(())
337 }
338
339 #[must_use]
340 pub const fn len() -> u16 {
341 8
343 }
344}
345
346#[derive(Clone, Copy, Debug, PartialEq, Eq)]
347pub enum CommandFlag {
348 RequestAck,
349 CommandResend,
350}
351
352impl CommandFlag {
353 fn serialize(self, mut buf: impl Write) -> Result<()> {
354 let flag_id: u16 = match self {
355 Self::RequestAck => 1 << 14,
356 Self::CommandResend => 1 << 15,
357 };
358
359 buf.write_bytes_le(flag_id)?;
360 Ok(())
361 }
362}
363
364#[derive(Clone, Copy, Debug, PartialEq, Eq)]
365pub enum ScdKind {
366 ReadMem,
367 WriteMem,
368 ReadMemStacked,
369 WriteMemStacked,
370}
371
372impl ScdKind {
373 fn serialize(self, mut buf: impl Write) -> Result<()> {
374 let kind_id: u16 = match self {
375 Self::ReadMem => 0x0800,
376 Self::WriteMem => 0x0802,
377 Self::ReadMemStacked => 0x0806,
378 Self::WriteMemStacked => 0x0808,
379 };
380
381 buf.write_bytes_le(kind_id)?;
382 Ok(())
383 }
384}
385
386pub trait CommandScd: std::fmt::Debug + Sized {
387 fn flag(&self) -> CommandFlag;
388
389 fn scd_kind(&self) -> ScdKind;
390
391 fn scd_len(&self) -> u16;
392
393 fn serialize(&self, buf: impl Write) -> Result<()>;
394
395 fn ack_scd_len(&self) -> u16;
396
397 fn finalize(self, request_id: u16) -> CommandPacket<Self> {
398 CommandPacket::new(self, request_id)
399 }
400}
401
402impl CommandScd for ReadMem {
403 fn flag(&self) -> CommandFlag {
404 CommandFlag::RequestAck
405 }
406
407 fn scd_kind(&self) -> ScdKind {
408 ScdKind::ReadMem
409 }
410
411 fn scd_len(&self) -> u16 {
412 12
414 }
415
416 fn serialize(&self, mut buf: impl Write) -> Result<()> {
417 buf.write_bytes_le(self.address)?;
418 buf.write_bytes_le(0_u16)?; buf.write_bytes_le(self.read_length)?;
420 Ok(())
421 }
422
423 fn ack_scd_len(&self) -> u16 {
424 self.read_length
425 }
426}
427
428impl CommandScd for WriteMem<'_> {
429 fn flag(&self) -> CommandFlag {
430 CommandFlag::RequestAck
431 }
432
433 fn scd_kind(&self) -> ScdKind {
434 ScdKind::WriteMem
435 }
436
437 fn scd_len(&self) -> u16 {
438 self.len
439 }
440
441 fn serialize(&self, mut buf: impl Write) -> Result<()> {
442 buf.write_bytes_le(self.address)?;
443 buf.write_all(self.data)?;
444 Ok(())
445 }
446
447 fn ack_scd_len(&self) -> u16 {
448 4
450 }
451}
452
453impl CommandScd for ReadMemStacked {
454 fn flag(&self) -> CommandFlag {
455 CommandFlag::RequestAck
456 }
457
458 fn scd_kind(&self) -> ScdKind {
459 ScdKind::ReadMemStacked
460 }
461
462 fn scd_len(&self) -> u16 {
463 self.len
464 }
465
466 fn serialize(&self, mut buf: impl Write) -> Result<()> {
467 for ent in &self.entries {
468 ent.serialize(&mut buf)?;
469 }
470 Ok(())
471 }
472
473 fn ack_scd_len(&self) -> u16 {
474 self.ack_scd_len
475 }
476}
477
478impl CommandScd for WriteMemStacked<'_> {
479 fn flag(&self) -> CommandFlag {
480 CommandFlag::RequestAck
481 }
482
483 fn scd_kind(&self) -> ScdKind {
484 ScdKind::WriteMemStacked
485 }
486
487 fn scd_len(&self) -> u16 {
488 self.len
490 }
491
492 fn serialize(&self, mut buf: impl Write) -> Result<()> {
493 for ent in &self.entries {
494 buf.write_bytes_le(ent.address)?;
495 buf.write_bytes_le(0_u16)?; buf.write_bytes_le(ent.data_len)?;
497 buf.write_all(ent.data)?;
498 }
499 Ok(())
500 }
501
502 fn ack_scd_len(&self) -> u16 {
503 self.ack_scd_len
504 }
505}
506
507fn into_scd_len(len: usize) -> Result<u16> {
508 len.try_into()
509 .map_err(|_| Error::InvalidPacket("scd length must be less than u16::MAX".into()))
510}
511
512#[cfg(test)]
513mod tests {
514 use super::*;
515
516 const HEADER_LEN: u8 = 4 + 8; fn serialize_header(command_id: [u8; 2], scd_len: [u8; 2], req_id: [u8; 2]) -> Vec<u8> {
519 let mut ccd = vec![];
520 ccd.write_bytes_le(0x4356_3355_u32).unwrap(); ccd.extend([0x00, 0x40]); ccd.extend(command_id);
523 ccd.extend(scd_len);
524 ccd.extend(req_id);
525 ccd
526 }
527
528 #[test]
529 fn test_read_mem_cmd() {
530 let command = ReadMem::new(0x0004, 64).finalize(1);
531 let scd_len = 12;
532
533 assert_eq!(command.cmd_len(), (HEADER_LEN + scd_len).into());
534 assert_eq!(command.request_id(), 1);
535
536 let mut buf = vec![];
537 command.serialize(&mut buf).unwrap();
538 let mut expected = serialize_header([0x00, 0x08], [scd_len, 0x00], [0x01, 0x00]);
539 expected.extend(vec![0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); expected.extend(vec![0x00, 0x00]); expected.extend(vec![64, 0x00]); assert_eq!(buf, expected);
544 }
545
546 #[test]
547 fn test_write_mem_cmd() {
548 let command = WriteMem::new(0x0004, &[0x01, 0x02, 0x03])
549 .unwrap()
550 .finalize(1);
551 let scd_len = 11;
552
553 assert_eq!(command.cmd_len(), (HEADER_LEN + scd_len).into());
554 assert_eq!(command.request_id(), 1);
555
556 let mut buf = vec![];
557 command.serialize(&mut buf).unwrap();
558 let mut expected = serialize_header([0x02, 0x08], [scd_len, 0x00], [0x01, 0x00]);
559 expected.extend(vec![0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); expected.extend(vec![0x01, 0x02, 0x03]); assert_eq!(buf, expected);
563 }
564
565 #[test]
566 fn test_read_mem_stacked() {
567 let read_mems = vec![ReadMem::new(0x0004, 4), ReadMem::new(0x0008, 8)];
568 let command = ReadMemStacked::new(read_mems).unwrap().finalize(1);
569 let scd_len = 12 * 2;
570
571 assert_eq!(command.cmd_len(), (HEADER_LEN + scd_len).into());
572 assert_eq!(command.request_id(), 1);
573
574 let mut buf = vec![];
575 command.serialize(&mut buf).unwrap();
576 let mut expected = serialize_header([0x06, 0x08], [12 * 2, 0x00], [0x01, 0x00]);
577 expected.extend(vec![0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); expected.extend(vec![0x00, 0x00]); expected.extend(vec![4, 0x00]); expected.extend(vec![0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); expected.extend(vec![0x00, 0x00]); expected.extend(vec![8, 0x00]); assert_eq!(buf, expected);
585 }
586
587 #[test]
588 fn test_write_mem_stacked() {
589 let write_mems = vec![
590 WriteMem::new(0x0004, &[0x01, 0x02, 0x03, 0x04]).unwrap(),
591 WriteMem::new(0x0008, &[0x11, 0x12, 0x13, 0x14]).unwrap(),
592 ];
593
594 let command = WriteMemStacked::new(write_mems).unwrap().finalize(1);
595 let scd_len = (12 + 4) * 2;
596
597 assert_eq!(command.cmd_len(), (HEADER_LEN + scd_len).into());
598 assert_eq!(command.request_id(), 1);
599
600 let mut buf = vec![];
601 command.serialize(&mut buf).unwrap();
602 let mut expected = serialize_header([0x08, 0x08], [scd_len, 0x00], [0x01, 0x00]);
603 expected.extend(vec![0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); expected.extend(vec![0x00, 0x00]); expected.extend(vec![4, 0x00]); expected.extend(vec![0x01, 0x02, 0x03, 0x04]); expected.extend(vec![0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); expected.extend(vec![0x00, 0x00]); expected.extend(vec![4, 0x00]); expected.extend(vec![0x11, 0x12, 0x13, 0x14]); assert_eq!(buf, expected);
613 }
614
615 #[test]
616 fn test_read_mem_chunks() {
617 let read_mem = ReadMem::new(0, 128);
618 let chunks: Vec<_> = read_mem.chunks(24).unwrap().collect();
619
620 let mut expected_addr = 0;
621 let mut read_len = 0;
622 for (i, chunk) in chunks.iter().enumerate().take(chunks.len() - 1) {
623 assert_eq!(chunk.address, expected_addr);
624 expected_addr += u64::from(chunk.read_length);
625 read_len += chunk.read_length;
626 assert_eq!(chunk.clone().finalize(i as u16).maximum_ack_len(), 24);
627 }
628
629 let last_chunk = chunks.last().unwrap();
630 assert_eq!(last_chunk.address, expected_addr);
631 assert_eq!(last_chunk.read_length + read_len, read_mem.read_length);
632 }
633
634 #[test]
635 fn test_write_mem_chunks() {
636 let data = vec![0; 128];
637 let write_mem = WriteMem::new(0, &data).unwrap();
638
639 let mut expected_addr = 0;
640 let mut sent_data_len = 0;
641
642 let chunks: Vec<_> = write_mem.chunks(24).unwrap().collect();
643
644 for (i, chunk) in chunks.iter().enumerate().take(chunks.len() - 1) {
645 assert_eq!(chunk.address, expected_addr);
646 expected_addr += u64::from(chunk.data_len);
647 sent_data_len += chunk.data_len;
648
649 assert_eq!(chunk.clone().finalize(i as u16).cmd_len(), 24);
650 }
651
652 let last_chunk = chunks.last().unwrap();
653 assert_eq!(last_chunk.address, expected_addr);
654 assert_eq!(last_chunk.data_len, data.len() as u16 - sent_data_len);
655 }
656}