portus/serialize/
changeprog.rs

1//! CCP sends this message to change the datapath program currently in use.
2
3use super::{u32_to_u8s, u64_to_u8s, AsRawMsg, RawMsg, HDR_LENGTH};
4use crate::lang::Reg;
5use crate::{Error, Result};
6use std::io::prelude::*;
7
8pub(crate) const CHANGEPROG: u8 = 4;
9
10#[derive(Clone, Debug, PartialEq)]
11pub struct Msg {
12    pub sid: u32,
13    pub program_uid: u32,
14    pub num_fields: u32,
15    pub fields: Vec<(Reg, u64)>,
16}
17
18impl AsRawMsg for Msg {
19    fn get_hdr(&self) -> (u8, u32, u32) {
20        (
21            CHANGEPROG,
22            HDR_LENGTH + 4 + 4 + self.num_fields * 13, // Reg size = 5, u64 size = 8
23            self.sid,
24        )
25    }
26
27    fn get_u32s<W: Write>(&self, w: &mut W) -> Result<()> {
28        let mut buf = [0u8; 4];
29        u32_to_u8s(&mut buf, self.program_uid);
30        w.write_all(&buf[..])?;
31        u32_to_u8s(&mut buf, self.num_fields);
32        w.write_all(&buf[..])?;
33        Ok(())
34    }
35
36    fn get_bytes<W: Write>(&self, w: &mut W) -> Result<()> {
37        let mut buf = [0u8; 8];
38        for f in &self.fields {
39            let reg =
40                f.0.clone()
41                    .into_iter()
42                    .map(|e| e.map_err(Error::from))
43                    .collect::<Result<Vec<u8>>>()?;
44            w.write_all(&reg[..])?;
45            u64_to_u8s(&mut buf, f.1);
46            w.write_all(&buf[..])?;
47        }
48        Ok(())
49    }
50
51    // at least for now, portus does not have to worry about deserializing this message
52    fn from_raw_msg(_msg: RawMsg) -> Result<Self> {
53        unimplemented!();
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use crate::lang::Reg;
60
61    #[test]
62    fn serialize_changeprog_msg() {
63        let m = super::Msg {
64            sid: 1,
65            program_uid: 7,
66            num_fields: 1,
67            fields: vec![(Reg::Implicit(4, crate::lang::Type::Num(None)), 42)],
68        };
69
70        let buf: Vec<u8> =
71            crate::serialize::serialize::<super::Msg>(&m.clone()).expect("serialize");
72        #[rustfmt::skip]
73        assert_eq!(
74            buf,
75            vec![
76                4, 0,                                     // CHANGEPROG
77                29, 0,                                    // length = 12
78                1, 0, 0, 0,                               // sock_id = 1
79                7, 0, 0, 0,                               // program_uid = 7
80                1, 0, 0, 0,                               // num_fields = 1
81                2, 4, 0, 0, 0, 0x2a, 0, 0, 0, 0, 0, 0, 0, // Reg::Implicit(4) <- 42
82            ],
83        );
84    }
85}