symcode/acute32/
decoder.rs

1use bit_vec::BitVec;
2use crate::interfaces::Decoder;
3use super::{Acute32SymcodeConfig, GlyphLabel};
4
5pub struct Acute32Decoder<'a> {
6    #[allow(dead_code)]
7    config: &'a Acute32SymcodeConfig,
8}
9
10impl<'a> Acute32Decoder<'a> {
11    pub fn new(config: &'a Acute32SymcodeConfig) -> Acute32Decoder<'a> {
12        Self { config }
13    }
14}
15
16// Dummy implementation, error detection/correction will be supported later
17impl Decoder for Acute32Decoder<'_> {
18    type Symbol = GlyphLabel;
19
20    type Err = &'static str;
21
22    fn decode(&self, encoded_data: Vec<Self::Symbol>) -> Result<BitVec, Self::Err> {
23        let num_bits_per_symbol = self.num_bits_per_symbol();
24        let mut decoded_data = vec![];
25        for &symbol in encoded_data.iter() {
26            if let Some(bit_vec) = GlyphLabel::self_to_bit_vec(symbol, num_bits_per_symbol) {
27                decoded_data.push(bit_vec);
28            } else {
29                return Err("Decoder error: Some recognized glyph is invalid.");
30            }
31        }
32
33        // Extract the first 20 bits as data payload, and the rest (5 bits) as checksum
34        let mut payload = BitVec::from_elem(20, false);
35        let mut checksum: u8 = 0;
36        for i in 0..25 {
37            let glyph_index = i / num_bits_per_symbol;
38            let within_glyph_offset = i % num_bits_per_symbol;
39            let bit = decoded_data[glyph_index].get(within_glyph_offset).unwrap();
40            if i < 20 {
41                payload.set(i, bit);
42            } else {
43                checksum <<= 1;
44                checksum += if bit {1} else {0};
45            }
46        }
47
48        if crczoo::crc5(&payload.to_bytes()) != checksum {
49            Err("Decoder error: Checksum fail")
50        } else {
51            Ok(payload)
52        }
53    }
54
55    fn num_bits_per_symbol(&self) -> usize {
56        crate::math::num_bits_to_store(GlyphLabel::num_variants())
57    }
58}