use hashbrown::{HashMap, HashSet};
use crate::cache::RecordPointer;
use crate::cache::{self, RecordId};
use crate::ntds::link_table_builder::LinkTableBuilder;
use crate::win32_types::Rdn;
use crate::{Membership, MembershipSet, SerializationType};
use super::DataTable;
pub struct LinkTable {
pub(crate) _forward_map: HashMap<RecordId, HashSet<RecordPointer>>,
pub(crate) backward_map: HashMap<RecordId, HashSet<RecordPointer>>,
}
impl LinkTable {
pub fn new<'info, 'db>(
link_table: cache::LinkTable<'info, 'db>,
data_table: &cache::DataTable<'info, 'db>,
schema_record_id: RecordPointer,
) -> crate::ntds::Result<Self> {
log::info!("reading link information and creating link_table cache");
let builder = LinkTableBuilder::from(link_table, data_table, schema_record_id)?;
builder.build(data_table.metadata())
}
pub(crate) fn member_of(&self, dnt: &RecordId) -> Option<&HashSet<RecordPointer>> {
self.backward_map.get(dnt)
}
pub fn member_names_of(&self, object_id: RecordId, data_table: &DataTable<'_, '_>) -> Vec<Rdn> {
let member_of = if let Some(children) = self.member_of(&object_id) {
children
.iter()
.map(|child_id| &data_table.data_table().metadata()[child_id])
.map(|record| record.rdn().clone())
.collect()
} else {
vec![]
};
member_of
}
pub fn member_refs_of<T: SerializationType>(
&self,
object_id: RecordId,
data_table: &DataTable<'_, '_>,
) -> MembershipSet<T> {
let member_of = if let Some(children) = self.member_of(&object_id) {
children
.iter()
.map(|child_id| &data_table.data_table().metadata()[child_id])
.map(|record| {
(
*record.record_ptr(),
record.rdn().clone(),
record.sid().clone(),
record.sam_account_name().clone(),
)
})
.collect()
} else {
vec![]
};
MembershipSet::<T>::from(member_of.into_iter().map(Membership::from))
}
}