use crate::errors::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Endian {
Little,
Big,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum PrimitiveType {
U8 = 0,
U16 = 1,
U32 = 2,
U64 = 3,
I8 = 4,
I16 = 5,
I32 = 6,
I64 = 7,
F32 = 8,
F64 = 9,
Bool = 10,
String = 11,
Bytes = 12,
Message = 13,
Vector = 14,
Unset = 255,
}
impl PrimitiveType {
pub fn size(self) -> Option<usize> {
match self {
PrimitiveType::U8 => Some(1),
PrimitiveType::U16 => Some(2),
PrimitiveType::U32 => Some(4),
PrimitiveType::U64 => Some(8),
PrimitiveType::I8 => Some(1),
PrimitiveType::I16 => Some(2),
PrimitiveType::I32 => Some(4),
PrimitiveType::I64 => Some(8),
PrimitiveType::F32 => Some(4),
PrimitiveType::F64 => Some(8),
PrimitiveType::Bool => Some(1),
PrimitiveType::String
| PrimitiveType::Bytes
| PrimitiveType::Message
| PrimitiveType::Vector
| PrimitiveType::Unset => None,
}
}
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(PrimitiveType::U8),
1 => Some(PrimitiveType::U16),
2 => Some(PrimitiveType::U32),
3 => Some(PrimitiveType::U64),
4 => Some(PrimitiveType::I8),
5 => Some(PrimitiveType::I16),
6 => Some(PrimitiveType::I32),
7 => Some(PrimitiveType::I64),
8 => Some(PrimitiveType::F32),
9 => Some(PrimitiveType::F64),
10 => Some(PrimitiveType::Bool),
11 => Some(PrimitiveType::String),
12 => Some(PrimitiveType::Bytes),
13 => Some(PrimitiveType::Message),
14 => Some(PrimitiveType::Vector),
255 => Some(PrimitiveType::Unset),
_ => None,
}
}
}
impl Endian {
#[inline]
pub fn read_u8(self, buf: &[u8], offset: usize) -> u8 {
buf[offset]
}
#[inline]
pub fn read_u16(self, buf: &[u8], offset: usize) -> u16 {
let bytes = &buf[offset..offset + 2];
match self {
Endian::Little => u16::from_le_bytes([bytes[0], bytes[1]]),
Endian::Big => u16::from_be_bytes([bytes[0], bytes[1]]),
}
}
#[inline]
pub fn read_u32(self, buf: &[u8], offset: usize) -> u32 {
let bytes = &buf[offset..offset + 4];
match self {
Endian::Little => u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
Endian::Big => u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
}
}
#[inline]
pub fn read_u64(self, buf: &[u8], offset: usize) -> u64 {
let bytes = &buf[offset..offset + 8];
match self {
Endian::Little => u64::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]),
Endian::Big => u64::from_be_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]),
}
}
#[inline]
pub fn read_i8(self, buf: &[u8], offset: usize) -> i8 {
self.read_u8(buf, offset) as i8
}
#[inline]
pub fn read_i16(self, buf: &[u8], offset: usize) -> i16 {
self.read_u16(buf, offset) as i16
}
#[inline]
pub fn read_i32(self, buf: &[u8], offset: usize) -> i32 {
self.read_u32(buf, offset) as i32
}
#[inline]
pub fn read_i64(self, buf: &[u8], offset: usize) -> i64 {
self.read_u64(buf, offset) as i64
}
#[inline]
pub fn read_f32(self, buf: &[u8], offset: usize) -> f32 {
f32::from_bits(self.read_u32(buf, offset))
}
#[inline]
pub fn read_f64(self, buf: &[u8], offset: usize) -> f64 {
f64::from_bits(self.read_u64(buf, offset))
}
#[inline]
pub fn read_bool(self, buf: &[u8], offset: usize) -> bool {
self.read_u8(buf, offset) != 0
}
#[inline]
pub fn write_u8(self, value: u8, buf: &mut [u8], offset: usize) {
buf[offset] = value;
}
#[inline]
pub fn write_u16(self, value: u16, buf: &mut [u8], offset: usize) {
let bytes = match self {
Endian::Little => value.to_le_bytes(),
Endian::Big => value.to_be_bytes(),
};
buf[offset..offset + 2].copy_from_slice(&bytes);
}
#[inline]
pub fn write_u32(self, value: u32, buf: &mut [u8], offset: usize) {
let bytes = match self {
Endian::Little => value.to_le_bytes(),
Endian::Big => value.to_be_bytes(),
};
buf[offset..offset + 4].copy_from_slice(&bytes);
}
#[inline]
pub fn write_u64(self, value: u64, buf: &mut [u8], offset: usize) {
let bytes = match self {
Endian::Little => value.to_le_bytes(),
Endian::Big => value.to_be_bytes(),
};
buf[offset..offset + 8].copy_from_slice(&bytes);
}
#[inline]
pub fn write_i8(self, value: i8, buf: &mut [u8], offset: usize) {
self.write_u8(value as u8, buf, offset);
}
#[inline]
pub fn write_i16(self, value: i16, buf: &mut [u8], offset: usize) {
self.write_u16(value as u16, buf, offset);
}
#[inline]
pub fn write_i32(self, value: i32, buf: &mut [u8], offset: usize) {
self.write_u32(value as u32, buf, offset);
}
#[inline]
pub fn write_i64(self, value: i64, buf: &mut [u8], offset: usize) {
self.write_u64(value as u64, buf, offset);
}
#[inline]
pub fn write_f32(self, value: f32, buf: &mut [u8], offset: usize) {
self.write_u32(value.to_bits(), buf, offset);
}
#[inline]
pub fn write_f64(self, value: f64, buf: &mut [u8], offset: usize) {
self.write_u64(value.to_bits(), buf, offset);
}
#[inline]
pub fn write_bool(self, value: bool, buf: &mut [u8], offset: usize) {
self.write_u8(value as u8, buf, offset);
}
}