varing/
char.rs

1use crate::utils::Buffer;
2
3use super::{
4  decode_u32_varint, encode_u32_varint, encode_u32_varint_to, encoded_u32_varint_len, DecodeError,
5  EncodeError, Varint,
6};
7
8/// A buffer for storing LEB128 encoded [`char`] value.
9pub type CharBuffer = Buffer<{ u32::MAX_ENCODED_LEN + 1 }>;
10
11/// Returns the encoded length of the value in LEB128 variable length format.
12/// The returned value will be in range [`char::ENCODED_LEN_RANGE`].
13#[inline]
14pub const fn encoded_char_len(char: &char) -> usize {
15  encoded_u32_varint_len(*char as u32)
16}
17
18/// Encodes a `char` value into LEB128 variable length format, and writes it to the buffer.
19#[inline]
20pub const fn encode_char(char: &char) -> CharBuffer {
21  encode_u32_varint(*char as u32)
22}
23
24/// Encodes a `char` value into LEB128 variable length format, and writes it to the buffer.
25#[inline]
26pub const fn encode_char_to(char: &char, buf: &mut [u8]) -> Result<usize, EncodeError> {
27  encode_u32_varint_to(*char as u32, buf)
28}
29
30/// Decodes a `char` in LEB128 encoded format from the buffer.
31///
32/// Returns the bytes readed and the decoded value if successful.
33#[inline]
34pub const fn decode_char(buf: &[u8]) -> Result<(usize, char), DecodeError> {
35  match decode_u32_varint(buf) {
36    Ok((bytes_read, value)) => match char::from_u32(value) {
37      Some(c) => Ok((bytes_read, c)),
38      None => Err(DecodeError::other("invalid char value")),
39    },
40    Err(e) => Err(e),
41  }
42}
43
44impl Varint for char {
45  const MIN_ENCODED_LEN: usize = u32::MIN_ENCODED_LEN;
46  const MAX_ENCODED_LEN: usize = u32::MAX_ENCODED_LEN;
47
48  #[inline]
49  fn encoded_len(&self) -> usize {
50    encoded_char_len(self)
51  }
52
53  #[inline]
54  fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
55    encode_char_to(self, buf)
56  }
57
58  #[inline]
59  fn decode(buf: &[u8]) -> Result<(usize, Self), DecodeError>
60  where
61    Self: Sized,
62  {
63    decode_char(buf)
64  }
65}
66
67#[cfg(test)]
68mod tests {
69  use super::*;
70
71  use quickcheck_macros::quickcheck;
72
73  #[quickcheck]
74  fn encode_decode_char(value: char) -> bool {
75    let encoded = encode_char(&value);
76    if encoded.len() != encoded_char_len(&value) || (encoded.len() > <char>::MAX_ENCODED_LEN) {
77      return false;
78    }
79
80    if let Ok((bytes_read, decoded)) = decode_char(&encoded) {
81      value == decoded && encoded.len() == bytes_read
82    } else {
83      false
84    }
85  }
86
87  #[quickcheck]
88  fn encode_decode_char_varint(value: char) -> bool {
89    let mut buf = [0; <char>::MAX_ENCODED_LEN];
90    let Ok(encoded_len) = value.encode(&mut buf) else {
91      return false;
92    };
93    if encoded_len != value.encoded_len() || (value.encoded_len() > <char>::MAX_ENCODED_LEN) {
94      return false;
95    }
96
97    if let Ok((bytes_read, decoded)) = <char>::decode(&buf) {
98      value == decoded && encoded_len == bytes_read
99    } else {
100      false
101    }
102  }
103}