use std::collections::HashMap;
use std::sync::{Arc, Mutex, OnceLock};
pub const EMBEDDED_REF_PREFIX: &str = "camel-embedded:";
const ENCODED_REF_PREFIX: &str = "camel-embedded%3A";
type Registry = HashMap<String, Arc<[u8]>>;
fn registry() -> &'static Mutex<Registry> {
static REGISTRY: OnceLock<Mutex<Registry>> = OnceLock::new();
REGISTRY.get_or_init(|| Mutex::new(HashMap::new()))
}
pub fn register(name: &str, bytes: Vec<u8>) {
let mut guard = registry().lock().unwrap_or_else(|p| p.into_inner());
guard.insert(name.to_owned(), Arc::from(bytes.into_boxed_slice()));
}
pub fn get(name: &str) -> Option<Arc<[u8]>> {
let guard = registry().lock().unwrap_or_else(|p| p.into_inner());
guard.get(name).cloned()
}
pub fn resolve_ref(value: &str) -> Option<Arc<[u8]>> {
if let Some(name) = value.strip_prefix(EMBEDDED_REF_PREFIX) {
return get(name);
}
if value.starts_with(ENCODED_REF_PREFIX) {
let decoded = percent_encoding::percent_decode_str(value)
.decode_utf8()
.ok()?;
let name = decoded.strip_prefix(EMBEDDED_REF_PREFIX)?;
return get(name);
}
None
}
#[cfg(test)]
mod tests {
use super::{register, resolve_ref};
use std::sync::Arc;
fn bytes(value: Option<Arc<[u8]>>) -> Vec<u8> {
value.expect("registered reference resolves").to_vec()
}
#[test]
fn encoded_prefix_is_the_canonical_prefix_with_encoded_colon() {
assert_eq!(
super::ENCODED_REF_PREFIX,
super::EMBEDDED_REF_PREFIX.replace(':', "%3A")
);
}
#[test]
fn resolve_ref_resolves_canonical_and_percent_encoded_spellings() {
register("assets/xslt/t.xslt", b"stylesheet-bytes".to_vec());
assert_eq!(
&bytes(resolve_ref("camel-embedded:assets/xslt/t.xslt"))[..],
b"stylesheet-bytes"
);
assert_eq!(
&bytes(resolve_ref("camel-embedded%3Aassets%2Fxslt%2Ft.xslt"))[..],
b"stylesheet-bytes"
);
}
#[test]
fn resolve_ref_canonical_suffix_is_literal() {
register("assets/x/a%20b.xslt", b"pct".to_vec());
register("assets/x/a b.xslt", b"space".to_vec());
assert_eq!(
&bytes(resolve_ref("camel-embedded:assets/x/a%20b.xslt"))[..],
b"pct",
"the canonical suffix must never be percent-decoded"
);
assert_eq!(
&bytes(resolve_ref("camel-embedded:assets/x/a b.xslt"))[..],
b"space"
);
}
#[test]
fn resolve_ref_encoded_handles_spaces_unicode_colon_and_double_encode() {
register("assets/styles/a b.xslt", b"s".to_vec());
register("assets/styles/ünïcode.xslt", b"u".to_vec());
register("assets/styles/a:b.xslt", b"c".to_vec());
register("assets/x/lit%20.xslt", b"litpct".to_vec());
register("assets/x/lit.xslt", b"lit".to_vec());
assert_eq!(
&bytes(resolve_ref("camel-embedded:assets/x/lit%20.xslt"))[..],
b"litpct"
);
assert_eq!(
&bytes(resolve_ref("camel-embedded:assets/x/lit.xslt"))[..],
b"lit"
);
register("assets/x/a%20b.xslt", b"pct".to_vec());
register("assets/x/a b.xslt", b"space".to_vec());
assert_eq!(
&bytes(resolve_ref("camel-embedded%3Aassets%2Fstyles%2Fa%20b.xslt"))[..],
b"s"
);
assert_eq!(
&bytes(resolve_ref(
"camel-embedded%3Aassets%2Fstyles%2F%C3%BCn%C3%AFcode.xslt"
))[..],
b"u"
);
assert_eq!(
&bytes(resolve_ref("camel-embedded%3Aassets%2Fstyles%2Fa%3Ab.xslt"))[..],
b"c"
);
assert_eq!(
&bytes(resolve_ref("camel-embedded%3Aassets%2Fx%2Fa%2520b.xslt"))[..],
b"pct"
);
assert_eq!(
&bytes(resolve_ref("camel-embedded%3Aassets%2Fx%2Fa%20b.xslt"))[..],
b"space"
);
assert!(
resolve_ref("camel-embedded%3Aassets%2Fx%2Flit%253A.xslt").is_none(),
"a double-encoded reference must decode exactly once"
);
}
#[test]
fn resolve_ref_fails_closed_on_unknown_or_plain_values() {
assert!(resolve_ref("plain/path").is_none());
assert!(resolve_ref("camel-embedded:assets/never-registered").is_none());
assert!(
resolve_ref("camel-embedded%3Aassets%2Fx%2F%FFbad").is_none(),
"invalid UTF-8 after percent-decoding must fail closed"
);
}
}