mod builder;
pub use builder::Builder;
use ltk_hash::{BinHash, WriteBytesExt as _};
use std::io;
use indexmap::IndexMap;
use ltk_io_ext::{measure, window_at};
use crate::{
stream::{layout::Numbering, owned},
traits::WriterExt as _,
};
use super::super::{Error, PropertyValueEnum};
use byteorder::{WriteBytesExt as _, LE};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Default)]
pub struct BinObject {
pub path_hash: BinHash,
pub class_hash: BinHash,
pub properties: IndexMap<BinHash, PropertyValueEnum>,
}
impl BinObject {
pub fn new(path_hash: impl Into<BinHash>, class_hash: impl Into<BinHash>) -> Self {
Self {
path_hash: path_hash.into(),
class_hash: class_hash.into(),
properties: IndexMap::default(),
}
}
pub fn builder(
path_hash: impl Into<BinHash>,
class_hash: impl Into<BinHash>,
) -> builder::Builder {
builder::Builder::new(path_hash, class_hash)
}
pub fn from_reader<R: io::Read + io::Seek + ?Sized>(
reader: &mut R,
class_hash: BinHash,
legacy: bool,
) -> Result<Self, Error> {
owned::read_object_from(reader, class_hash, Numbering::from_legacy(legacy))
}
pub fn to_writer<W: io::Write + io::Seek + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
let size_pos = writer.stream_position()?;
writer.write_u32::<LE>(0)?;
let (size, _) = measure(writer, |writer| {
writer.write_bin_hash::<LE>(self.path_hash)?;
writer.write_u16::<LE>(self.properties.len() as _)?;
for (name_hash, value) in self.properties.iter() {
writer.write_property(*name_hash, value)?;
}
Ok::<_, io::Error>(())
})?;
window_at(writer, size_pos, |writer| writer.write_u32::<LE>(size as _))?;
Ok(())
}
#[must_use]
#[inline(always)]
pub fn len(&self) -> usize {
self.properties.len()
}
#[must_use]
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.properties.is_empty()
}
#[must_use]
#[inline(always)]
pub fn get_property(&self, name_hash: BinHash) -> Option<&PropertyValueEnum> {
self.properties.get(&name_hash)
}
#[must_use]
#[inline(always)]
pub fn get_property_mut(&mut self, name_hash: BinHash) -> Option<&mut PropertyValueEnum> {
self.properties.get_mut(&name_hash)
}
#[must_use]
#[inline(always)]
pub fn contains_property(&self, name_hash: BinHash) -> bool {
self.properties.contains_key(&name_hash)
}
#[inline(always)]
pub fn insert(
&mut self,
name_hash: BinHash,
value: impl Into<PropertyValueEnum>,
) -> Option<PropertyValueEnum> {
self.properties.insert(name_hash, value.into())
}
pub fn remove_property(&mut self, name_hash: BinHash) -> Option<PropertyValueEnum> {
self.properties.shift_remove(&name_hash)
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (&BinHash, &PropertyValueEnum)> {
self.properties.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&BinHash, &mut PropertyValueEnum)> {
self.properties.iter_mut()
}
}
impl<'a> IntoIterator for &'a BinObject {
type Item = (&'a BinHash, &'a PropertyValueEnum);
type IntoIter = indexmap::map::Iter<'a, BinHash, PropertyValueEnum>;
fn into_iter(self) -> Self::IntoIter {
self.properties.iter()
}
}
impl<'a> IntoIterator for &'a mut BinObject {
type Item = (&'a BinHash, &'a mut PropertyValueEnum);
type IntoIter = indexmap::map::IterMut<'a, BinHash, PropertyValueEnum>;
fn into_iter(self) -> Self::IntoIter {
self.properties.iter_mut()
}
}
impl IntoIterator for BinObject {
type Item = (BinHash, PropertyValueEnum);
type IntoIter = indexmap::map::IntoIter<BinHash, PropertyValueEnum>;
fn into_iter(self) -> Self::IntoIter {
self.properties.into_iter()
}
}