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(&self, w: &mut W, bt_property_tag: u16) -> Result<()>; fn unmarshal_from(r: &mut R, bt_property_tag: u16) -> Result; } impl OctData for bool { fn marshal_to(&self, w: &mut W, _: u16) -> Result<()> { w.write_u8(u8::from(*self)) } fn unmarshal_from(r: &mut R, _: u16) -> Result { Ok(r.read_u8()? != 0) } } impl OctData for u8 { fn marshal_to(&self, w: &mut W, _: u16) -> Result<()> { w.write_u8(*self) } fn unmarshal_from(r: &mut R, _: u16) -> Result { r.read_u8() } } impl OctData for i8 { fn marshal_to(&self, w: &mut W, _: u16) -> Result<()> { w.write_i8(*self) } fn unmarshal_from(r: &mut R, _: u16) -> Result { r.read_i8() } } macro_rules! impl_primitive { ($($t:ty, $write:ident, $read:ident,)*) => { $( impl OctData for $t { fn marshal_to(&self, w: &mut W, _: u16) -> Result<()> { w.$write::(*self) } fn unmarshal_from(r: &mut R, _: u16) -> Result { r.$read::() } } )* }; } 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(&self, w: &mut W, _: u16) -> Result<()> { w.write_u32::(self.to_bits()) } fn unmarshal_from(r: &mut R, _: u16) -> Result { Ok(Self::from_bits(r.read_u32::()?)) } } impl OctData for f64 { fn marshal_to(&self, w: &mut W, _: u16) -> Result<()> { w.write_u64::(self.to_bits()) } fn unmarshal_from(r: &mut R, _: u16) -> Result { Ok(Self::from_bits(r.read_u64::()?)) } } impl OctData for Vec where T: OctData, { fn marshal_to(&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: &mut R, bt_property_tag: u16) -> Result { 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 OctData for HashMap where K: OctData + Eq + Hash + Ord, V: OctData, { default fn marshal_to(&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: &mut R, bt_property_tag: u16) -> Result { 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 OctData for DoubleKeyHashMap where K1: OctData + Eq + Hash + Ord, K2: OctData + Eq + Hash + Ord, V: OctData, { fn marshal_to(&self, w: &mut W, bt_property_tag: u16) -> Result<()> { self.iter() .map(|(_, inner_map)| inner_map.len() as i32) .sum::() .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: &mut R, bt_property_tag: u16) -> Result { 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 OctData for HashSet where T: OctData + Eq + Hash, { fn marshal_to(&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: &mut R, bt_property_tag: u16) -> Result { 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 OctData for Option where T: OctData, { fn marshal_to(&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: &mut R, bt_property_tag: u16) -> Result { Ok(Some(T::unmarshal_from(r, bt_property_tag)?)) } } impl OctData for String { fn marshal_to(&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: &mut R, bt_property_tag: u16) -> Result { 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(&self, w: &mut W, bt_property_tag: u16) -> Result<()> { self.as_ref().marshal_to(w, bt_property_tag) } fn unmarshal_from(r: &mut R, bt_property_tag: u16) -> Result { Ok(Cow::Owned(T::unmarshal_from(r, bt_property_tag)?)) } }