use super::{value_selector, EntryWithTokenizedSelector, OrderableTerm};
use crate::encryption::{
json_indexer::{
path_values::PathSegment,
prefix_mac::{PrefixMac, UpdatePrefixMac},
ste_vec::Selector,
},
Plaintext,
};
use serde_json::Value;
#[cfg_attr(test, derive(Debug))]
pub struct PlaintextEntry<'p> {
path: Vec<PathSegment<'p>>,
term: Option<OrderableTerm>,
value: &'p Value,
plaintext: Plaintext,
parent_is_array: bool,
}
impl<'p> PlaintextEntry<'p> {
pub(crate) fn new(path: Vec<PathSegment<'p>>, value: &'p Value) -> Self {
let parent_is_array = matches!(
path.last().expect("path cannot be empty"),
PathSegment::ArrayItem | PathSegment::ArrayPositionItem(_)
);
Self {
path,
term: OrderableTerm::for_json_value(value),
value,
plaintext: Plaintext::from(value.clone()),
parent_is_array,
}
}
pub(crate) fn build_selector<const N: usize, M>(
self,
macca: &mut M,
) -> EntryWithTokenizedSelector<N>
where
for<'u> M: PrefixMac
+ UpdatePrefixMac<String>
+ UpdatePrefixMac<&'u str>
+ UpdatePrefixMac<[u8; N]>,
{
let tokenized_selector = Selector::from_path(self.path).tokenize(macca);
let value_selector =
value_selector::tokenize_value_selector(&tokenized_selector, self.value, macca);
EntryWithTokenizedSelector::new(
tokenized_selector,
value_selector,
self.term,
self.plaintext,
self.parent_is_array,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
assert_was_finalized_with,
encryption::json_indexer::{
path_values::PathSegment,
ste_vec::{priv_state::ste_plaintext_term::OrderableTerm, tests::TestPrefixMac},
},
};
#[test]
fn test_entry_build_selector_mac_build() {
use PathSegment::*;
fn build_selector(path_segments: Vec<PathSegment<'_>>) -> TestPrefixMac {
let mut macca: TestPrefixMac = Default::default();
let value = Value::Null;
let _ = PlaintextEntry::new(path_segments, &value).build_selector::<16, _>(&mut macca);
macca
}
assert_was_finalized_with!(build_selector(vec![Root]), "$", "NULL00", [0u8; 16]);
assert_was_finalized_with!(
build_selector(vec![Root, ObjectItem("name")]),
"$['name']",
"NULL00",
[0u8; 16]
);
assert_was_finalized_with!(
build_selector(vec![Root, ObjectItem("name"), ArrayWildcardItem]),
"$['name'][*]",
"NULL00",
[0u8; 16]
);
assert_was_finalized_with!(
build_selector(vec![Root, ArrayWildcardItem, ObjectItem("name")]),
"$[*]['name']",
"NULL00",
[0u8; 16]
);
}
#[test]
fn test_value_selector_includes_canonical_value_bytes() {
use PathSegment::*;
let mut macca: TestPrefixMac = Default::default();
let value = Value::String("secret".into());
let _ = PlaintextEntry::new(vec![Root, ObjectItem("name")], &value)
.build_selector::<16, _>(&mut macca);
assert_was_finalized_with!(macca, "$['name']", "STRING", [0u8; 16], "secret");
}
#[test]
fn test_entry_build_selector_term() {
use PathSegment::*;
fn build_selector(value: Value) -> Option<OrderableTerm> {
let mut macca: TestPrefixMac = Default::default();
PlaintextEntry::new(vec![Root, ObjectItem("name")], &value)
.build_selector::<16, _>(&mut macca)
.term
}
assert_eq!(build_selector(Value::Null), None);
assert_eq!(build_selector(Value::Object(Default::default())), None);
assert_eq!(build_selector(Value::Array(Default::default())), None);
assert_eq!(build_selector(Value::Bool(true)), None);
assert_eq!(build_selector(Value::Bool(false)), None);
assert_eq!(
build_selector(Value::String(String::from("secret"))),
Some(OrderableTerm::String(String::from("secret")))
);
}
}