pub const MAJOR_VERSION: u8 = 4;
pub const MINOR_VERSION: u8 = 8;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u8)]
pub enum Tag {
Nil = b'0',
True = b'T',
False = b'F',
Fixnum = b'i',
Extended = b'e',
UClass = b'C',
Object = b'o',
Data = b'd',
UserDef = b'u',
UserMarshal = b'U',
Float = b'f',
Bignum = b'l',
String = b'"',
Regexp = b'/',
Array = b'[',
Hash = b'{',
HashDefault = b'}',
Struct = b'S',
ModuleOld = b'M',
Class = b'c',
Module = b'm',
Symbol = b':',
SymLink = b';',
Ivar = b'I',
Link = b'@',
}
impl Tag {
#[inline]
#[must_use]
pub const fn from_byte(byte: u8) -> Option<Self> {
Some(match byte {
b'0' => Self::Nil,
b'T' => Self::True,
b'F' => Self::False,
b'i' => Self::Fixnum,
b'e' => Self::Extended,
b'C' => Self::UClass,
b'o' => Self::Object,
b'd' => Self::Data,
b'u' => Self::UserDef,
b'U' => Self::UserMarshal,
b'f' => Self::Float,
b'l' => Self::Bignum,
b'"' => Self::String,
b'/' => Self::Regexp,
b'[' => Self::Array,
b'{' => Self::Hash,
b'}' => Self::HashDefault,
b'S' => Self::Struct,
b'M' => Self::ModuleOld,
b'c' => Self::Class,
b'm' => Self::Module,
b':' => Self::Symbol,
b';' => Self::SymLink,
b'I' => Self::Ivar,
b'@' => Self::Link,
_ => return None,
})
}
#[inline]
#[must_use]
pub const fn byte(self) -> u8 {
self as u8
}
}
pub const SIGN_POSITIVE: u8 = b'+';
pub const SIGN_NEGATIVE: u8 = b'-';
pub const REGEXP_IGNORE_CASE: u8 = 1 << 0;
pub const REGEXP_EXTENDED: u8 = 1 << 1;
pub const REGEXP_MULTILINE: u8 = 1 << 2;
#[allow(clippy::cast_sign_loss)]
#[inline]
#[must_use]
pub fn decode_int(lead: i8, tail: &[u8]) -> i32 {
match lead {
0 => 0,
1..=4 => {
let size = lead as usize;
let mut buf = [0u8; 4];
buf[..size].copy_from_slice(&tail[..size]);
i32::from_le_bytes(buf)
}
-4..=-1 => {
let size = lead.unsigned_abs() as usize;
let mut buf = [0xffu8; 4];
buf[..size].copy_from_slice(&tail[..size]);
i32::from_le_bytes(buf)
}
_ => {
if lead > 0 {
i32::from(lead) - 5
} else {
i32::from(lead) + 5
}
}
}
}
#[allow(clippy::cast_sign_loss)]
#[inline]
#[must_use]
pub const fn packed_int_tail_len(lead: i8) -> usize {
match lead {
1..=4 => lead as usize,
-4..=-1 => (-lead) as usize,
_ => 0,
}
}
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap)]
#[inline]
#[must_use]
pub fn encode_int(value: i32, buf: &mut [u8; 5]) -> &[u8] {
if value == 0 {
buf[0] = 0;
return &buf[..1];
}
if (1..123).contains(&value) {
buf[0] = (value + 5) as u8;
return &buf[..1];
}
if (-123..0).contains(&value) {
buf[0] = (value - 5) as u8;
return &buf[..1];
}
let mut v = value;
let mut i = 1usize;
loop {
buf[i] = (v & 0xff) as u8;
v >>= 8;
if v == 0 {
buf[0] = i as u8;
break;
}
if v == -1 {
buf[0] = (-(i as i32)) as u8;
break;
}
i += 1;
}
&buf[..=i]
}