mail-server/crates/jmap-proto/src/parser/base32.rs
2024-07-17 18:33:22 +02:00

65 lines
1.8 KiB
Rust

/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd <hello@stalw.art>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use utils::codec::{base32_custom::BASE32_INVERSE, leb128::Leb128Iterator};
use super::json::Parser;
#[derive(Debug)]
pub struct JsonBase32Reader<'x, 'y> {
bytes: &'y mut Parser<'x>,
last_byte: u8,
pos: usize,
}
impl<'x, 'y> JsonBase32Reader<'x, 'y> {
pub fn new(bytes: &'y mut Parser<'x>) -> Self {
JsonBase32Reader {
bytes,
pos: 0,
last_byte: 0,
}
}
#[inline(always)]
fn map_byte(&mut self) -> Option<u8> {
match self.bytes.next_unescaped() {
Ok(Some(byte)) => match BASE32_INVERSE[byte as usize] {
decoded_byte if decoded_byte != u8::MAX => {
self.last_byte = decoded_byte;
Some(decoded_byte)
}
_ => None,
},
_ => None,
}
}
pub fn error(&mut self) -> trc::Error {
self.bytes.error_value()
}
}
impl<'x, 'y> Iterator for JsonBase32Reader<'x, 'y> {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
let pos = self.pos % 5;
let last_byte = self.last_byte;
let byte = self.map_byte()?;
self.pos += 1;
match pos {
0 => ((byte << 3) | (self.map_byte().unwrap_or(0) >> 2)).into(),
1 => ((last_byte << 6) | (byte << 1) | (self.map_byte().unwrap_or(0) >> 4)).into(),
2 => ((last_byte << 4) | (byte >> 1)).into(),
3 => ((last_byte << 7) | (byte << 2) | (self.map_byte().unwrap_or(0) >> 3)).into(),
4 => ((last_byte << 5) | byte).into(),
_ => None,
}
}
}
impl<'x, 'y> Leb128Iterator<u8> for JsonBase32Reader<'x, 'y> {}