279 lines
7.9 KiB
Rust
279 lines
7.9 KiB
Rust
use std::{
|
|
borrow::Cow,
|
|
collections::{HashMap, HashSet},
|
|
hash::Hash,
|
|
io::{Read, Result, Write},
|
|
};
|
|
|
|
use byteorder::{ReadBytesExt, WriteBytesExt};
|
|
use itertools::Itertools;
|
|
|
|
pub use qwer_derive::OctData;
|
|
|
|
use crate::DoubleKeyHashMap;
|
|
|
|
// LE encoded data
|
|
pub trait OctData: Sized + Send + Sync {
|
|
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()>;
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self>;
|
|
}
|
|
|
|
impl OctData for bool {
|
|
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
|
w.write_u8(u8::from(*self))
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
|
Ok(r.read_u8()? != 0)
|
|
}
|
|
}
|
|
|
|
impl OctData for u8 {
|
|
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
|
w.write_u8(*self)
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
|
r.read_u8()
|
|
}
|
|
}
|
|
|
|
impl OctData for i8 {
|
|
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
|
w.write_i8(*self)
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
|
r.read_i8()
|
|
}
|
|
}
|
|
|
|
macro_rules! impl_primitive {
|
|
($($t:ty, $write:ident, $read:ident,)*) => {
|
|
$(
|
|
impl OctData for $t {
|
|
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
|
w.$write::<byteorder::LittleEndian>(*self)
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
|
r.$read::<byteorder::LittleEndian>()
|
|
}
|
|
}
|
|
)*
|
|
};
|
|
}
|
|
|
|
impl_primitive! {
|
|
u16, write_u16, read_u16,
|
|
i16, write_i16, read_i16,
|
|
u32, write_u32, read_u32,
|
|
i32, write_i32, read_i32,
|
|
u64, write_u64, read_u64,
|
|
i64, write_i64, read_i64,
|
|
}
|
|
|
|
// floats are a bit special, the bits are casted to an integer and then treated as an integer
|
|
|
|
impl OctData for f32 {
|
|
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
|
w.write_u32::<byteorder::LittleEndian>(self.to_bits())
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
|
Ok(Self::from_bits(r.read_u32::<byteorder::LittleEndian>()?))
|
|
}
|
|
}
|
|
|
|
impl OctData for f64 {
|
|
fn marshal_to<W: Write>(&self, w: &mut W, _: u16) -> Result<()> {
|
|
w.write_u64::<byteorder::LittleEndian>(self.to_bits())
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, _: u16) -> Result<Self> {
|
|
Ok(Self::from_bits(r.read_u64::<byteorder::LittleEndian>()?))
|
|
}
|
|
}
|
|
|
|
impl<T> OctData for Vec<T>
|
|
where
|
|
T: OctData,
|
|
{
|
|
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
|
if self.is_empty() {
|
|
(0i32).marshal_to(w, bt_property_tag)?;
|
|
return Ok(());
|
|
}
|
|
(self.len() as i32).marshal_to(w, bt_property_tag)?;
|
|
for item in self {
|
|
item.marshal_to(w, bt_property_tag)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
|
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
|
if len < 0 {
|
|
let real_len = -len;
|
|
let mut vec = Self::with_capacity(real_len as usize);
|
|
for _ in 0..real_len {
|
|
bool::unmarshal_from(r, bt_property_tag)?;
|
|
vec.push(T::unmarshal_from(r, bt_property_tag)?);
|
|
}
|
|
Ok(vec)
|
|
} else {
|
|
let mut vec = Self::with_capacity(len as usize);
|
|
for _ in 0..len {
|
|
vec.push(T::unmarshal_from(r, bt_property_tag)?);
|
|
}
|
|
Ok(vec)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<K, V> OctData for HashMap<K, V>
|
|
where
|
|
K: OctData + Eq + Hash + Ord,
|
|
V: OctData,
|
|
{
|
|
default fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
|
(self.len() as i32).marshal_to(w, bt_property_tag)?;
|
|
for (key, value) in self.iter().sorted_by_key(|kv| kv.0) {
|
|
key.marshal_to(w, bt_property_tag)?;
|
|
value.marshal_to(w, bt_property_tag)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
default fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
|
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
|
if len == -1 {
|
|
return Ok(Self::new());
|
|
}
|
|
let mut map = Self::with_capacity(len as usize);
|
|
for _ in 0..len {
|
|
map.insert(
|
|
K::unmarshal_from(r, bt_property_tag)?,
|
|
V::unmarshal_from(r, bt_property_tag)?,
|
|
);
|
|
}
|
|
Ok(map)
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "collection")]
|
|
impl<K1, K2, V> OctData for DoubleKeyHashMap<K1, K2, V>
|
|
where
|
|
K1: OctData + Eq + Hash + Ord,
|
|
K2: OctData + Eq + Hash + Ord,
|
|
V: OctData,
|
|
{
|
|
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
|
self.iter()
|
|
.map(|(_, inner_map)| inner_map.len() as i32)
|
|
.sum::<i32>()
|
|
.marshal_to(w, bt_property_tag)?;
|
|
for (key1, inner_map) in self {
|
|
for (key2, value) in inner_map {
|
|
key1.marshal_to(w, bt_property_tag)?;
|
|
key2.marshal_to(w, bt_property_tag)?;
|
|
value.marshal_to(w, bt_property_tag)?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
|
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
|
if len == -1 {
|
|
return Ok(Self::new());
|
|
}
|
|
let mut map = Self::new();
|
|
for _ in 0..len {
|
|
let key1 = K1::unmarshal_from(r, bt_property_tag)?;
|
|
let key2 = K2::unmarshal_from(r, bt_property_tag)?;
|
|
let value = V::unmarshal_from(r, bt_property_tag)?;
|
|
map.entry(key1)
|
|
.or_insert_with(HashMap::new)
|
|
.insert(key2, value);
|
|
}
|
|
Ok(map)
|
|
}
|
|
}
|
|
|
|
impl<T> OctData for HashSet<T>
|
|
where
|
|
T: OctData + Eq + Hash,
|
|
{
|
|
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
|
(self.len() as i32).marshal_to(w, bt_property_tag)?;
|
|
for item in self {
|
|
item.marshal_to(w, bt_property_tag)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
|
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
|
if len == -1 {
|
|
return Ok(Self::new());
|
|
}
|
|
let mut set = Self::with_capacity(len as usize);
|
|
for _ in 0..len {
|
|
set.insert(T::unmarshal_from(r, bt_property_tag)?);
|
|
}
|
|
Ok(set)
|
|
}
|
|
}
|
|
|
|
impl<T> OctData for Option<T>
|
|
where
|
|
T: OctData,
|
|
{
|
|
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
|
if let Some(item) = self {
|
|
item.marshal_to(w, bt_property_tag)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
|
Ok(Some(T::unmarshal_from(r, bt_property_tag)?))
|
|
}
|
|
}
|
|
|
|
impl OctData for String {
|
|
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
|
if self.is_empty() {
|
|
(-1i32).marshal_to(w, bt_property_tag)?;
|
|
return Ok(());
|
|
}
|
|
(self.len() as i32).marshal_to(w, bt_property_tag)?;
|
|
w.write_all(self.as_bytes())
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
|
let len = i32::unmarshal_from(r, bt_property_tag)?;
|
|
if len == -1 {
|
|
return Ok(Self::new());
|
|
}
|
|
let mut buf = vec![0; len as usize];
|
|
r.read_exact(&mut buf)?;
|
|
Ok(Self::from_utf8(buf).unwrap())
|
|
}
|
|
}
|
|
|
|
impl<'a, T> OctData for Cow<'a, T>
|
|
where
|
|
T: OctData + Clone,
|
|
{
|
|
fn marshal_to<W: Write>(&self, w: &mut W, bt_property_tag: u16) -> Result<()> {
|
|
self.as_ref().marshal_to(w, bt_property_tag)
|
|
}
|
|
|
|
fn unmarshal_from<R: Read>(r: &mut R, bt_property_tag: u16) -> Result<Self> {
|
|
Ok(Cow::Owned(T::unmarshal_from(r, bt_property_tag)?))
|
|
}
|
|
}
|