nimbi_protocol/messages/
check_update.rs1use microdot::{
2 helpers::{Header, SerializeStructHelper, HEADER_SIZE},
3 Deserialize, MicrodotError, Serialize,
4};
5
6use crate::types::{Id, Version};
7
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9#[derive(Debug)]
10pub struct CheckUpdateRequest<'a> {
11 pub program_id: Id<'a>,
12 pub release_channel_id: Id<'a>,
13 pub current_version: Version,
14}
15
16impl Serialize for CheckUpdateRequest<'_> {
17 fn serialize(&self, buf: &mut [u8]) -> Result<usize, MicrodotError> {
18 let mut helper = SerializeStructHelper::new(buf);
19
20 helper.serialize_fields(&[
21 &self.program_id,
22 &self.release_channel_id,
23 &self.current_version,
24 ])
25 }
26}
27
28impl<'a> Deserialize<'a> for CheckUpdateRequest<'a> {
29 fn deserialize(buf: &'a [u8]) -> Result<Self, MicrodotError> {
30 let mut offset = 0;
31
32 let mut program_id = None;
33 let mut release_channel_id = None;
34 let mut current_version = None;
35
36 while offset < buf.len() {
37 let header = Header::deserialize(&buf[offset..offset + HEADER_SIZE])?;
38 let buf = &buf[offset + HEADER_SIZE..offset + HEADER_SIZE + header.size];
39
40 match header.id {
41 1 => {
42 program_id = Some(Id::deserialize(buf)?);
43 }
44 2 => {
45 release_channel_id = Some(Id::deserialize(buf)?);
46 }
47 3 => {
48 current_version = Some(Version::deserialize(buf)?);
49 }
50 _ => return Err(MicrodotError::invalid_payload()),
51 }
52
53 offset += HEADER_SIZE + header.size;
54 }
55
56 let Some(program_id) = program_id else {
57 return Err(MicrodotError::missing_field("program_id"));
58 };
59
60 let Some(release_channel_id) = release_channel_id else {
61 return Err(MicrodotError::missing_field("release_channel_id"));
62 };
63
64 let Some(current_version) = current_version else {
65 return Err(MicrodotError::missing_field("current_version"));
66 };
67
68 Ok(Self {
69 program_id,
70 release_channel_id,
71 current_version,
72 })
73 }
74}
75
76#[cfg_attr(feature = "defmt", derive(defmt::Format))]
77#[derive(Debug)]
78pub struct CheckUpdateResponse {
79 pub next_version: Version,
80}
81
82impl Serialize for CheckUpdateResponse {
83 fn serialize(&self, buf: &mut [u8]) -> Result<usize, MicrodotError> {
84 let mut helper = SerializeStructHelper::new(buf);
85
86 helper.serialize_field(&self.next_version)
87 }
88}
89
90impl<'a> Deserialize<'a> for CheckUpdateResponse {
91 fn deserialize(buf: &'a [u8]) -> Result<Self, MicrodotError> {
92 let mut offset = 0;
93
94 let mut next_version = None;
95
96 while offset < buf.len() {
97 let header = Header::deserialize(&buf[offset..offset + HEADER_SIZE])?;
98 let buf = &buf[offset + HEADER_SIZE..offset + HEADER_SIZE + header.size];
99
100 match header.id {
101 1 => {
102 next_version = Some(Version::deserialize(buf)?);
103 }
104 _ => return Err(MicrodotError::invalid_payload()),
105 }
106
107 offset += HEADER_SIZE + header.size;
108 }
109
110 let Some(next_version) = next_version else {
111 return Err(MicrodotError::missing_field("next_version"));
112 };
113
114 Ok(Self { next_version })
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn check_update_response_should_serialize() {
124 let payload = CheckUpdateResponse {
125 next_version: Version::new(1, 2, 3),
126 };
127
128 let mut buf = [0u8; 16];
129
130 match payload.serialize(&mut buf) {
131 Ok(bytes_written) => {
132 assert_eq!(bytes_written, 9);
133 assert_eq!(&buf[..bytes_written], &[1, 0, 6, 0, 1, 0, 2, 0, 3]);
134 }
135 Err(err) => {
136 dbg!(err);
137
138 unreachable!();
139 }
140 }
141 }
142
143 #[test]
144 fn check_update_response_should_deserialize() {
145 let buf = &[1, 0, 6, 0, 1, 0, 2, 0, 3];
146
147 match CheckUpdateResponse::deserialize(buf) {
148 Ok(response) => {
149 assert_eq!(response.next_version, Version::new(1, 2, 3,));
150 }
151 Err(err) => {
152 dbg!(err);
153
154 unreachable!();
155 }
156 }
157 }
158}