rustot/ota/encoding/
mod.rs1#[cfg(feature = "ota_mqtt_data")]
2pub mod cbor;
3pub mod json;
4
5use core::ops::{Deref, DerefMut};
6use core::str::FromStr;
7use serde::{Serialize, Serializer};
8
9use crate::jobs::StatusDetailsOwned;
10
11use self::json::{JobStatusReason, OtaJob, Signature};
12
13use super::error::OtaError;
14use super::{config::Config, pal::Version};
15
16#[derive(Clone, PartialEq)]
17pub struct Bitmap(bitmaps::Bitmap<32>);
18
19impl Bitmap {
20 pub fn new(file_size: usize, block_size: usize, block_offset: u32) -> Self {
21 let total_num_blocks = (file_size + block_size - 1) / block_size;
23
24 Self(bitmaps::Bitmap::mask(core::cmp::min(
25 32 - 1,
26 total_num_blocks - block_offset as usize,
27 )))
28 }
29}
30
31impl Deref for Bitmap {
32 type Target = bitmaps::Bitmap<32>;
33
34 fn deref(&self) -> &Self::Target {
35 &self.0
36 }
37}
38
39impl DerefMut for Bitmap {
40 fn deref_mut(&mut self) -> &mut Self::Target {
41 &mut self.0
42 }
43}
44
45impl Serialize for Bitmap {
46 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
47 where
48 S: Serializer,
49 {
50 Serializer::serialize_bytes(serializer, &self.deref().into_value().to_le_bytes())
51 }
52}
53
54#[derive(Clone)]
58pub struct FileContext {
59 pub filepath: heapless::String<64>,
60 pub filesize: usize,
61 pub fileid: u8,
62 pub certfile: heapless::String<64>,
63 pub update_data_url: Option<heapless::String<64>>,
64 pub auth_scheme: Option<heapless::String<64>>,
65 pub signature: Signature,
66 pub file_type: Option<u32>,
67
68 pub status_details: StatusDetailsOwned,
69 pub block_offset: u32,
70 pub blocks_remaining: usize,
71 pub request_block_remaining: u32,
72 pub job_name: heapless::String<64>,
73 pub stream_name: heapless::String<64>,
74 pub bitmap: Bitmap,
75}
76
77impl FileContext {
78 pub fn new_from(
79 job_name: &str,
80 ota_job: &OtaJob,
81 status_details: Option<StatusDetailsOwned>,
82 file_idx: usize,
83 config: &Config,
84 current_version: Version,
85 ) -> Result<Self, OtaError> {
86 let file_desc = ota_job
87 .files
88 .get(file_idx)
89 .ok_or(OtaError::InvalidFile)?
90 .clone();
91
92 let status = if let Some(details) = status_details {
94 details
95 } else {
96 let mut status = StatusDetailsOwned::new();
97 status
98 .insert(
99 heapless::String::from("updated_by"),
100 current_version.to_string(),
101 )
102 .map_err(|_| OtaError::Overflow)?;
103 status
104 };
105
106 let signature = file_desc.signature();
107
108 let block_offset = 0;
109 let bitmap = Bitmap::new(file_desc.filesize, config.block_size, block_offset);
110
111 Ok(FileContext {
112 filepath: heapless::String::from(file_desc.filepath),
113 filesize: file_desc.filesize,
114 fileid: file_desc.fileid,
115 certfile: heapless::String::from(file_desc.certfile),
116 update_data_url: file_desc.update_data_url.map(heapless::String::from),
117 auth_scheme: file_desc.auth_scheme.map(heapless::String::from),
118 signature,
119 file_type: file_desc.file_type,
120
121 status_details: status,
122
123 job_name: heapless::String::from(job_name),
124 block_offset,
125 request_block_remaining: bitmap.len() as u32,
126 blocks_remaining: (file_desc.filesize + config.block_size - 1) / config.block_size,
127 stream_name: heapless::String::from(ota_job.streamname),
128 bitmap,
129 })
130 }
131
132 pub fn self_test(&self) -> bool {
133 self.status_details
134 .get(&heapless::String::from("self_test"))
135 .and_then(|f| f.parse().ok())
136 .map(|reason: JobStatusReason| {
137 reason == JobStatusReason::SigCheckPassed
138 || reason == JobStatusReason::SelfTestActive
139 })
140 .unwrap_or(false)
141 }
142
143 pub fn updated_by(&self) -> Option<Version> {
144 self.status_details
145 .get(&heapless::String::from("updated_by"))
146 .and_then(|s| Version::from_str(s.as_str()).ok())
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn bitmap_masking() {
156 let bitmap = Bitmap::new(255000, 256, 0);
157
158 let true_indices: Vec<usize> = bitmap.into_iter().collect();
159 assert_eq!((0..31).into_iter().collect::<Vec<usize>>(), true_indices);
160 }
161}