use wire::{
PrivacyAnswer, PrivacyControl, PrivacyControlEntry, PrivacyCurrent, PrivacyEditions,
PrivacyHistory, PrivacyHost, PrivacyIntent, PrivacyNotWrittenEntry, PrivacyOriginal,
PrivacyOriginalLine, PrivacyOutcome, PrivacyTarget, PrivacyValue,
};
use super::controls::definition;
use super::fault::ReadFault;
use super::originals::{Disposition, original};
use super::state::{Holdings, Intent};
use super::target::Snapshot;
pub(super) fn answer(
host: PrivacyHost,
mut read: impl FnMut(PrivacyControl) -> Option<Result<Snapshot, ReadFault>>,
history: PrivacyHistory,
outcomes: Vec<PrivacyOutcome>,
) -> PrivacyAnswer {
let edition = match &host {
PrivacyHost::Windows(windows) => windows.edition,
PrivacyHost::Unreadable { .. } | PrivacyHost::NotWindows => None,
};
let controls = PrivacyControl::ALL
.into_iter()
.map(|control| {
let row = definition(control);
let current = read(control);
PrivacyControlEntry {
control,
category: row.category,
originals: PrivacyOriginal::ALL
.into_iter()
.filter(|&item| {
matches!(original(item).disposition, Disposition::Writes(writes) if writes == control)
})
.map(line)
.collect(),
target: PrivacyTarget::from(&row.target),
scope: row.target.kind().scope(),
editions: PrivacyEditions {
honoured: row.editions.honoured.to_vec(),
ignored: row.editions.ignored.to_vec(),
},
host_fit: row.editions.fit(edition),
build_effect: row.build_effect,
written: match ¤t {
Some(Ok(snapshot)) => row.written.target(snapshot).as_ref().map(PrivacyValue::from),
Some(Err(_)) | None => None,
},
current: match current {
None => PrivacyCurrent::NotRead,
Some(Ok(snapshot)) => PrivacyCurrent::Read {
value: PrivacyValue::from(&snapshot),
},
Some(Err(ReadFault::AccessDenied)) => PrivacyCurrent::AccessDenied,
Some(Err(ReadFault::Failed(error))) => PrivacyCurrent::Failed { error },
},
}
})
.collect();
let not_written = PrivacyOriginal::ALL
.into_iter()
.filter_map(|item| match original(item).disposition {
Disposition::Writes(_) => None,
Disposition::NotWritten {
reason,
alternatives,
} => Some(PrivacyNotWrittenEntry {
line: line(item),
reason,
alternatives: alternatives.to_vec(),
}),
})
.collect();
PrivacyAnswer {
host,
controls,
not_written,
history,
outcomes,
}
}
pub(super) fn disclosed(holdings: &Holdings<'_, ()>) -> PrivacyHistory {
PrivacyHistory::Disclosed {
owned: holdings.owned().map(intent).collect(),
unresolved: holdings.unresolved().map(intent),
}
}
fn intent(intent: &Intent) -> PrivacyIntent {
PrivacyIntent {
operation: intent.operation.get(),
control: intent.control,
original: PrivacyValue::from(&intent.original),
modified: PrivacyValue::from(&intent.modified),
restore_of: intent.restore_of.map(std::num::NonZeroU64::get),
}
}
fn line(item: PrivacyOriginal) -> PrivacyOriginalLine {
PrivacyOriginalLine {
item,
text: original(item).text.to_owned(),
}
}