async_coap/
block.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16use std::convert::From;
17use std::fmt::{Debug, Display, Formatter};
18
19/// Type for interpreting `block1` and `block2` option values.
20#[derive(Copy, Clone, Eq, Ord, Hash, PartialOrd, PartialEq)]
21pub struct BlockInfo(pub u32);
22
23impl BlockInfo {
24    const MORE_FLAG: u32 = 0b1000;
25
26    /// Maximum legal value for `num`.
27    pub const NUM_MAX: u32 = ((1 << 20) - 1);
28
29    const SZX_RESERVED: u8 = 0b0111;
30
31    /// Maximum legal value for `szx`.
32    pub const SZX_MAX: u8 = Self::SZX_RESERVED - 1;
33
34    /// Constructs a new `BlockInfo` from the number, more flag, and size exponent.
35    pub fn new(num: u32, m: bool, szx: u8) -> Option<BlockInfo> {
36        if num > Self::NUM_MAX || szx > Self::SZX_MAX {
37            None
38        } else {
39            Some(BlockInfo((num << 4) + ((m as u32) << 3) + szx as u32))
40        }
41    }
42
43    /// Block number value.
44    #[inline]
45    pub fn num(&self) -> u32 {
46        self.0 >> 4
47    }
48
49    /// More flag value. If set, there are more blocks to follow.
50    #[inline]
51    pub fn more_flag(&self) -> bool {
52        (self.0 & Self::MORE_FLAG) == Self::MORE_FLAG
53    }
54
55    /// Block size exponent field value.
56    #[inline]
57    pub fn szx(&self) -> u8 {
58        self.0 as u8 & 0b111
59    }
60
61    /// The offset (in bytes) that this block starts at.
62    #[inline]
63    pub fn offset(&self) -> usize {
64        let val = self.0 as usize;
65        (val & !0xF) << (val & 0b0111)
66    }
67
68    /// The length of this block, in bytes.
69    #[inline]
70    pub fn len(&self) -> usize {
71        1 << (self.szx() as usize + 4)
72    }
73
74    /// Determines if calling [`BlockInfo::next`] will yield the next block or not.
75    ///
76    /// If this method returns true, calling [`BlockInfo::next`] will fail.
77    pub fn is_max_block(&self) -> bool {
78        self.num() == Self::NUM_MAX
79    }
80
81    /// Checks the validity of the contained value.
82    pub fn is_invalid(&self) -> bool {
83        (self.num() > Self::NUM_MAX) || self.szx() == Self::SZX_RESERVED
84    }
85
86    /// Checks the contained value for validity and, if valid, returns it in an `Option`.
87    pub fn valid(self) -> Option<BlockInfo> {
88        if self.is_invalid() {
89            None
90        } else {
91            Some(self)
92        }
93    }
94
95    /// Calculates what the next block will be, if any.
96    pub fn next(&self) -> Option<BlockInfo> {
97        if self.num() < Self::NUM_MAX {
98            BlockInfo(self.0 + 0x10).valid()
99        } else {
100            None
101        }
102    }
103
104    /// Calculates a smaller block size that maintains this block's offset.
105    pub fn smaller(&self) -> Option<BlockInfo> {
106        let szx = self.szx();
107        if szx != Self::SZX_RESERVED && szx > 0 {
108            Self::new(self.num() * 2, self.more_flag(), szx - 1)
109        } else {
110            None
111        }
112    }
113
114    /// Returns this `BlockInfo`'s value *with* the more flag set.
115    pub fn with_more_flag(&self) -> BlockInfo {
116        BlockInfo(self.0 | Self::MORE_FLAG)
117    }
118
119    /// Returns this `BlockInfo`'s value *without* the more flag set.
120    pub fn without_more_flag(&self) -> BlockInfo {
121        BlockInfo(self.0 & !Self::MORE_FLAG)
122    }
123}
124
125impl From<u32> for BlockInfo {
126    fn from(x: u32) -> Self {
127        BlockInfo(x)
128    }
129}
130
131impl Default for BlockInfo {
132    /// Returns a block info with an offset of zero and a block size of 1024.
133    fn default() -> Self {
134        BlockInfo(6)
135    }
136}
137
138impl Display for BlockInfo {
139    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
140        write!(
141            f,
142            "{}/{}/{}",
143            self.num(),
144            self.more_flag() as u8,
145            self.len()
146        )?;
147        if self.is_invalid() {
148            f.write_str("(!)")
149        } else {
150            Ok(())
151        }
152    }
153}
154
155impl Debug for BlockInfo {
156    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
157        write!(f, "BlockInfo(0x{:06X})", self.0)?;
158        Display::fmt(self, f)?;
159        f.write_str(")")
160    }
161}
162
163/// Tool for reconstructing block-wise messages.
164///
165/// This mechanism was designed so that it can be used successfully with `block1` (request payload)
166/// and `block2` (response payload) messages.
167#[derive(Debug)]
168pub struct BlockReconstructor<F> {
169    next_block: BlockInfo,
170    is_finished: bool,
171    write: F,
172}
173
174impl<F: Default + std::io::Write> Default for BlockReconstructor<F> {
175    fn default() -> Self {
176        BlockReconstructor::new(F::default(), Default::default())
177    }
178}
179
180impl<F> BlockReconstructor<F>
181where
182    F: std::io::Write,
183{
184    /// Creates a new instance of `BlockReconstructor`.
185    pub fn new(write: F, next_block: BlockInfo) -> BlockReconstructor<F> {
186        BlockReconstructor {
187            next_block: next_block.without_more_flag(),
188            is_finished: false,
189            write,
190        }
191    }
192
193    /// The next block this object wants.
194    pub fn next_block(&self) -> BlockInfo {
195        self.next_block
196    }
197
198    /// Returns true if we have received all of our blocks and have no additional processing
199    /// to perform.
200    pub fn is_finished(&self) -> bool {
201        self.is_finished
202    }
203
204    /// Consumes this object and returns the underlying `std::io::Write` instance.
205    pub fn into_inner(self) -> F {
206        self.write
207    }
208
209    /// Feeds a block (with an associated payload) to the reconstructor.
210    pub fn feed(&mut self, block: BlockInfo, payload: &[u8]) -> Result<bool, ()> {
211        if self.is_finished {
212            return Ok(true);
213        }
214
215        if block.offset() < self.next_block.offset() {
216            // Ignore blocks we have already seen.
217            return Ok(false);
218        }
219
220        if block.offset() > self.next_block.offset() {
221            // This isn't the block we were expecting.
222            return Err(());
223        }
224
225        if !block.more_flag() {
226            self.is_finished = true;
227        } else if block.len() > payload.len() {
228            // Not enough data?
229            return Err(());
230        } else if block.len() < payload.len() {
231            // Extra data?
232            return Err(());
233        } else if let Some(next_block) = block.without_more_flag().next() {
234            self.next_block = next_block;
235        } else {
236            // Call to `next()` failed.
237            return Err(());
238        }
239
240        self.write.write_all(payload).map_err(|_| ())?;
241
242        Ok(self.is_finished)
243    }
244}
245
246#[cfg(test)]
247mod tests {
248    use super::*;
249
250    #[test]
251    fn defaults() {
252        let block = BlockInfo::default();
253        assert_eq!(false, block.more_flag());
254        assert_eq!(6, block.szx());
255        assert_eq!(0, block.num());
256        assert_eq!(1024, block.len());
257        assert_eq!(0, block.offset());
258        assert_eq!(false, block.is_max_block());
259        assert_eq!(false, block.is_invalid());
260    }
261
262    #[test]
263    fn next() {
264        let block = BlockInfo::default().next().unwrap();
265        assert_eq!(BlockInfo::default().more_flag(), block.more_flag());
266        assert_eq!(6, block.szx());
267        assert_eq!(1, block.num());
268        assert_eq!(1024, block.len());
269        assert_eq!(1024, block.offset());
270        assert_eq!(false, block.is_max_block());
271        assert_eq!(false, block.is_invalid());
272    }
273
274    #[test]
275    fn smaller() {
276        let block = BlockInfo::default().smaller().unwrap();
277        assert_eq!(BlockInfo::default().more_flag(), block.more_flag());
278        assert_eq!(5, block.szx());
279        assert_eq!(0, block.num());
280        assert_eq!(512, block.len());
281        assert_eq!(0, block.offset());
282        assert_eq!(false, block.is_max_block());
283        assert_eq!(false, block.is_invalid());
284    }
285
286    #[test]
287    fn next_smaller() {
288        let block = BlockInfo::default().next().unwrap().smaller().unwrap();
289        assert_eq!(BlockInfo::default().more_flag(), block.more_flag());
290        assert_eq!(5, block.szx());
291        assert_eq!(2, block.num());
292        assert_eq!(512, block.len());
293        assert_eq!(1024, block.offset());
294        assert_eq!(false, block.is_max_block());
295        assert_eq!(false, block.is_invalid());
296
297        let smaller = block.smaller().unwrap();
298        assert_eq!(256, smaller.len());
299        assert_eq!(block.offset(), smaller.offset());
300    }
301
302    #[test]
303    fn with_and_without_more_flag() {
304        let block = BlockInfo::default().without_more_flag();
305        assert_eq!(false, block.more_flag());
306        assert_eq!(6, block.szx());
307        assert_eq!(0, block.num());
308        assert_eq!(1024, block.len());
309        assert_eq!(0, block.offset());
310        assert_eq!(false, block.is_max_block());
311        assert_eq!(false, block.is_invalid());
312
313        let block = block.with_more_flag();
314        assert_eq!(true, block.more_flag());
315        assert_eq!(6, block.szx());
316        assert_eq!(0, block.num());
317        assert_eq!(1024, block.len());
318        assert_eq!(0, block.offset());
319        assert_eq!(false, block.is_max_block());
320        assert_eq!(false, block.is_invalid());
321    }
322
323    #[test]
324    fn check_next() {
325        let block = BlockInfo::new(BlockInfo::NUM_MAX - 1, true, 6).unwrap();
326        assert_eq!(true, block.more_flag());
327        assert_eq!(6, block.szx());
328        assert_eq!(BlockInfo::NUM_MAX - 1, block.num());
329        assert_eq!(1024, block.len());
330        assert_eq!(1073739776, block.offset());
331        assert_eq!(false, block.is_max_block());
332        assert_eq!(false, block.is_invalid());
333
334        let block = block.next().unwrap();
335
336        assert_eq!(true, block.more_flag());
337        assert_eq!(6, block.szx());
338        assert_eq!(BlockInfo::NUM_MAX, block.num());
339        assert_eq!(1024, block.len());
340        assert_eq!(1073739776 + 1024, block.offset());
341        assert_eq!(true, block.is_max_block());
342        assert_eq!(false, block.is_invalid());
343
344        assert_eq!(None, block.next());
345    }
346
347    #[test]
348    fn check_smaller() {
349        let block = BlockInfo::new(BlockInfo::NUM_MAX - 1, true, 6).unwrap();
350        assert_eq!(false, block.is_invalid());
351        assert_eq!(None, block.smaller());
352
353        let block = BlockInfo(0);
354        assert_eq!(false, block.is_invalid());
355        assert_eq!(None, block.smaller());
356    }
357
358    #[test]
359    fn validity() {
360        let block = BlockInfo(0);
361        assert_eq!(false, block.is_invalid());
362        assert_eq!(false, block.smaller().is_some());
363        assert_eq!(true, block.next().is_some());
364        assert_eq!(Some(block), block.valid());
365
366        let block = BlockInfo(1);
367        assert_eq!(false, block.is_invalid());
368        assert_eq!(true, block.smaller().is_some());
369        assert_eq!(true, block.next().is_some());
370        assert_eq!(Some(block), block.valid());
371
372        let block = BlockInfo(!0);
373        assert_eq!(true, block.is_invalid());
374        assert_eq!(None, block.smaller());
375        assert_eq!(None, block.next());
376        assert_eq!(None, block.valid());
377
378        let block = BlockInfo(BlockInfo::SZX_RESERVED as u32);
379        assert_eq!(true, block.is_invalid());
380        assert_eq!(None, block.smaller());
381        assert_eq!(None, block.next());
382        assert_eq!(None, block.valid());
383
384        let block = BlockInfo(BlockInfo::SZX_RESERVED as u32);
385        assert_eq!(true, block.is_invalid());
386        assert_eq!(None, block.smaller());
387        assert_eq!(None, block.next());
388        assert_eq!(None, block.valid());
389    }
390}