saddle-core 0.3.37

Shared contracts for Saddle components
Documentation
//! Borrowed selectors over the same event projection; no intermediate JSON tree.
use super::*;
use crate::{context_json::RedactedSubtree, json_pointer::{JsonPointer, PointerSegment}};
pub struct SelectedContextValue<'a>(Value<'a>);
enum Value<'a> {
    Full(UnifiedContext<'a>), Json(JsonSubtree<'a>), Protected(RedactedSubtree<'a>), Text(&'a str),
    Id(u64), Integer(i64), Attempt(u32), Identity(ContextIdentity), Label(ContextLabel), Phase(RequestViewPhase), Span(SpanProjection), Operation(RegisteredContextOperation),
    Application(Application), Trace(Trace<'a>), Request(Request<'a>), Interface(Interface<'a>), Input(Input<'a>),
    Call(Call<'a>), Execution(Execution<'a>), Auth(Auth<'a>), Meta(Meta<'a>), States(FieldStates<'a>), Redactions(Redactions<'a>), Empty,
}
impl Serialize for SelectedContextValue<'_> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        macro_rules! serialize { ($($variant:ident),*) => { match &self.0 {
            $(Value::$variant(v) => v.serialize(s),)*
            Value::Id(v) => StringId(*v).serialize(s), Value::Empty => Empty.serialize(s),
        } }; }
        serialize!(Full, Json, Protected, Text, Integer, Attempt, Identity, Label, Phase, Span, Operation,
            Application, Trace, Request, Interface, Input, Call, Execution, Auth, Meta, States, Redactions)
    }
}
fn split(path: &str) -> Option<(PointerSegment<'_>, &str)> {
    let first = JsonPointer::parse(path).ok()?.segments().next()?;
    let raw = &path[1..]; Some((first, raw.find('/').map_or("", |at| &raw[at..])))
}
fn fact<'a, T>(value: ContextFact<T>, map: impl FnOnce(T) -> Value<'a>) -> Option<Value<'a>> {
    match value { ContextFact::Present(value) => Some(map(value)), _ => None }
}
impl UnifiedContext<'_> {
    /// The pointer is relative to context. Missing differs from a present null.
    /// The callback cannot keep any value borrowed from a managed source.
    ///
    /// ```compile_fail
    /// use saddle_core::request_context::{UnifiedContext, SelectedContextValue};
    /// fn escape<'a>(context: &UnifiedContext<'a>) -> Option<SelectedContextValue<'a>> {
    ///     context.with_selected("/business", |value| value).unwrap()
    /// }
    /// ```
    pub fn with_selected<R>(&self, path: &str, read: impl FnOnce(Option<SelectedContextValue<'_>>) -> R)
        -> Result<R, crate::json_pointer::InvalidJsonPointer> {
        JsonPointer::parse(path)?;
        if path.is_empty() { return Ok(read(Some(SelectedContextValue(Value::Full(UnifiedContext(self.0)))))); }
        let mut read = Some(read); let mut result = None;
        if let Some((group, rest)) = split(path) {
            if group.matches("business") {
                if let Some(source) = &self.0.inner.business {
                    source.with_tree_and_secrets(&mut |root, secrets| {
                        let selected = RedactedSubtree::new(root, secrets, "/business").pointer(rest).ok().flatten();
                        result = Some(read.take().unwrap()(selected.map(|v| SelectedContextValue(Value::Protected(v)))));
                    });
                } else { result = Some(read.take().unwrap()(rest.is_empty().then_some(SelectedContextValue(Value::Empty)))); }
                return Ok(result.expect("business source provides exactly one tree"));
            }
        }
        if let Some(ingress) = &self.0.inner.ingress {
            ingress.source.with_tree(&mut |tree| {
                result = Some(read.take().unwrap()(self.selected(path, Some(tree)).map(SelectedContextValue)));
            });
        } else { result = Some(read.take().unwrap()(self.selected(path, None).map(SelectedContextValue))); }
        Ok(result.expect("source provides exactly one immutable tree"))
    }
    fn selected<'a>(&'a self, path: &str, tree: Option<JsonSubtree<'a>>) -> Option<Value<'a>> {
        if path.is_empty() { return Some(Value::Full(UnifiedContext(self.0))); }
        let (group, rest) = split(path)?;
        let raw = |path| tree.and_then(|tree| tree.pointer(path).ok().flatten());
        let subtree = |source: Option<JsonSubtree<'a>>| source.and_then(|source| source.pointer(rest).ok().flatten()).map(Value::Json);
        let leaf = |name: &str| split(rest).is_some_and(|(field, tail)| tail.is_empty() && field.matches(name));
        let view = self.0; let snap = view.diagnostic_snapshot();
        if group.matches("schemaVersion") { return rest.is_empty().then_some(Value::Text("1.0")); }
        if group.matches("applicationInfo") {
            if rest.is_empty() { return Some(Value::Application(Application { application: view.inner.root.application })); }
            if leaf("application") { return Some(Value::Label(view.inner.root.application)); }
        }
        if group.matches("traceInfo") {
            let source = raw("/profuseGwContext/traceInfo");
            if rest.is_empty() { return Some(Value::Trace(Trace { view, source })); }
            if leaf("traceId") { return fact(snap.trace_id, Value::Identity); }
            if leaf("rpcId") { return fact(snap.rpc_id, Value::Identity); }
            if split(rest).is_some_and(|(field, _)| field.matches("traceId") || field.matches("rpcId")) { return None; }
            return subtree(source);
        }
        if group.matches("ldcInfo") { return subtree(raw("/profuseGwContext/ldcInfo")); }
        if group.matches("profuseContext") { return subtree(raw("/profuseContext")); }
        if group.matches("inputInfo") {
            let source = raw("/requestData");
            if rest.is_empty() { return Some(Value::Input(Input { request_data: source })); }
            let (field, tail) = split(rest)?;
            if field.matches("requestData") { return source.and_then(|s| s.pointer(tail).ok().flatten()).map(Value::Json); }
        }
        if group.matches("requestInfo") {
            if rest.is_empty() { return Some(Value::Request(Request(view))); }
            if leaf("localRequestId") { return Some(Value::Id(view.inner.root.local)); }
            if leaf("requestId") { return fact(snap.request, Value::Identity); }
            if leaf("callId") { return view.inner.ingress.as_ref().map(|i| Value::Identity(i.call_id)); }
            if leaf("deadlineUnixMs") { return view.inner.ingress.as_ref().map(|i| Value::Integer(i.deadline_unix_ms)); }
        }
        if group.matches("interfaceInfo") {
            if rest.is_empty() { return Some(Value::Interface(Interface(view))); }
            if leaf("entry") { return Some(Value::Text("profusegw")); }
            if leaf("interfaceId") { return view.identity().map(|i| Value::Label(i.route)); }
        }
        if group.matches("executionInfo") {
            if rest.is_empty() { return Some(Value::Execution(Execution(view))); }
            if leaf("taskId") { return fact(snap.task, Value::Id); }
            if leaf("scopeId") { return fact(snap.scope, |scope| Value::Id(scope.as_u64())); }
            if leaf("dbOperation") { return fact(snap.db_operation, Value::Operation); }
            if leaf("phase") { return Some(Value::Phase(view.inner.facts.phase)); }
        }
        if group.matches("callInfo") {
            if rest.is_empty() { return Some(Value::Call(Call(view))); }
            let child = view.inner.child.as_ref()?;
            if leaf("spanId") { return Some(Value::Span(SpanProjection(child.span))); }
            if leaf("attempt") { return Some(Value::Attempt(child.attempt)); }
            if leaf("service") { return Some(Value::Label(child.service)); }
            if leaf("method") { return Some(Value::Label(child.operation)); }
        }
        if group.matches("authInfo") {
            let subject = raw("/profuseGwContext/userInfo/userId");
            if rest.is_empty() { return Some(Value::Auth(Auth { state: "unavailable", subject })); }
            if leaf("state") { return Some(Value::Text("unavailable")); }
            if leaf("subjectId") { return subject.map(Value::Json); }
        }
        if group.matches("_meta") {
            if rest.is_empty() { return Some(Value::Meta(Meta { view, tree })); }
            if leaf("revision") { return Some(Value::Id(view.inner.revision)); }
            if leaf("scopeId") { return fact(snap.scope, |scope| Value::Id(scope.as_u64())); }
            let (field, tail) = split(rest)?;
            if field.matches("redactions") {
                if tail.is_empty() { return Some(Value::Redactions(Redactions(view))); }
                let (key, remaining) = split(tail)?;
                let mut marked = false;
                if remaining.is_empty() {
                    if let Some(source) = &view.inner.business {
                        source.with_secrets(&mut |paths| marked = paths.iter().any(|path| key.matches(path)));
                    }
                }
                if marked { return Some(Value::Text("secret")); }
            }
            if field.matches("fieldStates") {
                if tail.is_empty() { return Some(Value::States(FieldStates { view, tree })); }
                let (key, remaining) = split(tail)?;
                if !remaining.is_empty() { return None; }
                let mut buffer = [0; 1024];
                return state_at(view, tree, key.decode_into(&mut buffer).ok()?).map(Value::Text);
            }
        }
        None
    }
}
pub(super) fn state_at(view: &RequestExecutionView, tree: Option<JsonSubtree<'_>>, path: &str) -> Option<&'static str> {
    let snap = view.diagnostic_snapshot();
    match path {
        "/traceInfo/traceId" => state(snap.trace_id), "/traceInfo/rpcId" => state(snap.rpc_id), "/requestInfo/requestId" => state(snap.request),
        "/executionInfo/taskId" => state(snap.task), "/executionInfo/scopeId" => state(snap.scope), "/executionInfo/dbOperation" => state(snap.db_operation),
        "/interfaceInfo/module" | "/interfaceInfo/service" | "/interfaceInfo/operation" => Some("not_applicable"),
        "/interfaceInfo/interfaceId" => view.identity().is_none().then_some("not_established"),
        "/requestInfo/callId" | "/requestInfo/deadlineUnixMs" => view.inner.ingress.is_none().then_some(if view.identity().is_some() { "unavailable" } else { "not_established" }),
        "/inputInfo/requestData" | "/ldcInfo" | "/authInfo/subjectId" => view.inner.ingress.is_none().then_some("unavailable"),
        "/profuseContext" => tree.and_then(|tree| tree.pointer("/profuseContext").ok().flatten()).is_none().then_some(if tree.is_some() { "not_established" } else { "unavailable" }),
        "/callInfo/spanId" | "/callInfo/attempt" | "/callInfo/service" | "/callInfo/method" => view.inner.child.is_none().then_some("not_applicable"),
        "/callInfo/callId" | "/callInfo/parentCallId" | "/callInfo/kind" | "/callInfo/dependencyAlias" | "/callInfo/contractSha256" => Some(if view.inner.child.is_some() { "unavailable" } else { "not_applicable" }),
        _ => None,
    }
}