use std::{fmt::Display, io::{Cursor, ErrorKind, Read}};
use getset::Getters;
use crate::{value::{FromValue, StringOrStringSet, ToStringOrStringSet}, CDatabase};
#[derive(Getters, Eq, PartialEq)]
#[getset(get = "pub")]
pub struct AncestorsCol {
ancestors: Vec<i32>,
}
impl FromValue for AncestorsCol {
fn from_value_opt(value: &crate::cache::Value) -> crate::ntds::Result<Option<Self>>
where
Self: Sized,
{
let ancestors = match value {
crate::cache::Value::Null(_) => return Ok(None),
crate::cache::Value::U8(u) => vec![(*u).into()],
crate::cache::Value::U16(u) => vec![(*u).into()],
crate::cache::Value::I16(i) => vec![(*i).into()],
crate::cache::Value::I32(i) => vec![*i],
crate::cache::Value::Binary(items) | crate::cache::Value::Guid(items) => {
if items.len() % 4 != 0 {
return Err(crate::ntds::Error::InvalidValueDetected(
format!("{value:?}"),
"Binary",
));
}
let mut cursor = Cursor::new(&items[..]);
let mut ancestors = Vec::new();
let mut buf = [0; 4];
loop {
match cursor.read(&mut buf) {
Ok(4) => ancestors.push(i32::from_le_bytes(buf)),
Ok(0) => break,
Ok(x) => panic!("unexpected length of buffer, unexpectedly read {x} bytes"),
Err(why) if why.kind() == ErrorKind::UnexpectedEof => break,
Err(why) => return Err(why.into()),
}
}
ancestors
}
_ => {
return Err(crate::ntds::Error::InvalidValueDetected(
format!("{value:?}"),
"Binary",
))
}
};
Ok(Some(Self { ancestors }))
}
}
impl Display for AncestorsCol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.ancestors)
}
}
impl ToStringOrStringSet for AncestorsCol
{
fn to_string_or_stringset(&self, _database: &CDatabase<'_, '_>) -> StringOrStringSet {
StringOrStringSet::String(self.to_string())
}
}