use serde_json::Value;
use crate::context::TraceContext;
pub(super) fn server_capability(context: &TraceContext<'_>, path: &[&str]) -> Option<bool> {
capability_in(context.server_capabilities(), path, context)
}
pub(super) fn client_capability(context: &TraceContext<'_>, path: &[&str]) -> Option<bool> {
capability_in(context.client_capabilities(), path, context)
}
fn capability_in(
capabilities: Option<&Value>,
path: &[&str],
context: &TraceContext<'_>,
) -> Option<bool> {
context.initialize().result?;
let Some(mut current) = capabilities else {
return Some(false);
};
for segment in path {
match current.get(segment) {
Some(next) => current = next,
None => return Some(false),
}
}
Some(!(current.is_null() || matches!(current, Value::Bool(false))))
}
pub(super) fn is_base64(text: &str) -> bool {
let bytes = text.as_bytes();
if !bytes.len().is_multiple_of(4) {
return false;
}
let padding = bytes.iter().rev().take_while(|&&b| b == b'=').count();
if padding > 2 {
return false;
}
let content = &bytes[..bytes.len() - padding];
content
.iter()
.all(|&b| b.is_ascii_alphanumeric() || b == b'+' || b == b'/')
}
pub(super) fn has_rfc3986_scheme(uri: &str) -> bool {
let Some((scheme, _)) = uri.split_once(':') else {
return false;
};
let mut chars = scheme.chars();
let Some(first) = chars.next() else {
return false;
};
first.is_ascii_alphabetic()
&& chars.all(|c| c.is_ascii_alphanumeric() || matches!(c, '+' | '-' | '.'))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn base64_validation_is_exact() {
for valid in ["", "aGk=", "aGV5", "aGV5bw==", "AB+/", "QUJDRA=="] {
assert!(is_base64(valid), "{valid:?} should validate");
}
for invalid in [
"aGk", "aGk =", "aGk!", "====", "aG=k", "aGV5bw=", ] {
assert!(!is_base64(invalid), "{invalid:?} should not validate");
}
}
#[test]
fn rfc3986_scheme_validation_is_exact() {
for valid in ["https://x", "file:///a", "git://r", "a:", "z+ssh.2-x:rest"] {
assert!(has_rfc3986_scheme(valid), "{valid:?} should validate");
}
for invalid in [
"", "no-colon", ":rest", "1https://x", "ht tp://x", "ht_tp://x", ] {
assert!(
!has_rfc3986_scheme(invalid),
"{invalid:?} should not validate"
);
}
}
}