use super::*;
use std::sync::{Arc, Mutex, MutexGuard};
#[derive(Debug, Clone, Default)]
pub struct MockPwdGrpProvider(Arc<Mutex<Data>>);
#[derive(
Deftly, Debug, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash,
)]
#[derive_deftly_adhoc]
pub struct RealEffectiveSavedIds {
pub r: Id,
pub e: Id,
pub s: Id,
}
derive_deftly_adhoc! {
RealEffectiveSavedIds:
impl From<Id> for RealEffectiveSavedIds {
fn from(id: Id) -> Self {
RealEffectiveSavedIds {
$( $fname: id, )
}
}
}
}
#[derive(Debug, Clone, Deftly)]
#[derive_deftly_adhoc]
pub(crate) struct Data {
#[deftly(iter)]
pub(crate) passwd: Vec<Passwd<RawSafe>>,
#[deftly(iter)]
pub(crate) group: Vec<Group<RawSafe>>,
pub(crate) uids: RealEffectiveSavedIds,
pub(crate) gids: RealEffectiveSavedIds,
pub(crate) supplementary_groups: Vec<Id>,
}
impl Default for Data {
fn default() -> Self {
let s = |s: &str| s.to_string().into_bytes().into_boxed_slice();
Data {
passwd: vec![Passwd {
name: s("root"),
passwd: s("*"),
uid: 0,
gid: 0,
gecos: s("root"),
dir: s("/root"),
shell: s("/bin/bash"),
..Passwd::blank()
}],
group: vec![Group {
name: s("root"),
passwd: s("x"),
gid: 0,
mem: vec![].into(),
..Group::blank()
}],
uids: 1000.into(),
gids: 1000.into(),
supplementary_groups: vec![],
}
}
}
impl From<Data> for MockPwdGrpProvider {
fn from(data: Data) -> MockPwdGrpProvider {
MockPwdGrpProvider(Arc::new(Mutex::new(data)))
}
}
impl MockPwdGrpProvider {
pub fn new() -> Self {
MockPwdGrpProvider::default()
}
fn lock(&self) -> MutexGuard<'_, Data> {
self.0.lock().expect("lock poisoned")
}
}
impl SealedProvider for MockPwdGrpProvider {
fn with_mocks<R>(&self, f: impl FnOnce(SealedData) -> R) -> Option<R> {
Some(f(SealedData(&self.lock())))
}
}
impl PwdGrpProvider for MockPwdGrpProvider {}
derive_deftly_adhoc! {
Data expect items:
impl MockPwdGrpProvider {
pub fn new_empty() -> Self {
Data {
$( $fname: Default::default(), )
}.into()
}
$( ${select1 fmeta(iter) {
#[doc = stringify!($fname)]
pub fn ${paste add_to_ $fname s}<I>(
&self,
data: impl IntoIterator<Item=I>,
)
where I: Into<${pascal_case $fname}<RawSafe>>,
{
self.lock().$fname.extend(
data.into_iter().map(|ent| ent.into())
)
}
} else {
#[doc = stringify!($fname)]
pub fn ${paste set_ $fname}(
&self,
$fname: $ftype,
) {
self.lock().$fname = $fname;
}
}} )
}
}