use serde::{Deserialize, Serialize};
use crate::{
ejsonpath::{IndexArg, Selector},
encryption::json_indexer::{
path_values::PathSegment,
prefix_mac::{PrefixMac, UpdatePrefixMac},
},
};
impl Selector {
pub(crate) fn from_path(path: Vec<PathSegment>) -> Self {
path.into_iter()
.fold(Selector::Root, |acc, segment| match segment {
PathSegment::Root => acc,
PathSegment::ArrayWildcardItem => {
Selector::Index(Box::new(acc), IndexArg::Wildcard)
}
PathSegment::ArrayItem => Selector::Index(Box::new(acc), IndexArg::Item),
PathSegment::ArrayPositionItem(n) => {
Selector::Index(Box::new(acc), IndexArg::Number(n))
}
PathSegment::ObjectItem(key) => {
Selector::Index(Box::new(acc), IndexArg::Field(key.to_owned()))
}
})
}
pub(crate) fn tokenize<const N: usize, M>(self, macca: &mut M) -> TokenizedSelector<N>
where
M: PrefixMac + UpdatePrefixMac<String>,
{
macca.update(self.canonicalise().to_string());
TokenizedSelector(macca.finalize_reset())
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Copy)]
#[serde(transparent)]
pub struct TokenizedSelector<const N: usize>(
#[serde(
serialize_with = "hex::serde::serialize",
deserialize_with = "hex_decode_array"
)]
pub(crate) [u8; N],
);
impl<const N: usize> TokenizedSelector<N> {
pub fn as_bytes(&self) -> [u8; N] {
self.0
}
}
fn hex_decode_array<'de, const N: usize, D>(deserializer: D) -> Result<[u8; N], D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let mut out: [u8; N] = [0; N];
hex::decode_to_slice(s, &mut out).map_err(serde::de::Error::custom)?;
Ok(out)
}
#[cfg(test)]
mod test {
use super::super::tests::TestPrefixMac;
use crate::{assert_was_finalized_with, encryption::json_indexer::ste_vec::selector::Selector};
#[test]
fn test_tokenize() {
let mut macca: TestPrefixMac = Default::default();
let selector = Selector::parse("$.foo.bar[*]").unwrap();
let _ = selector.tokenize::<16, _>(&mut macca);
assert_was_finalized_with!(macca, "$['foo']['bar'][*]");
let mut macca: TestPrefixMac = Default::default();
let selector = Selector::parse("$.foo.bar").unwrap();
let _ = selector.tokenize::<16, _>(&mut macca);
assert_was_finalized_with!(macca, "$['foo']['bar']");
}
}