code-system-graph-core 1.0.0

Core extraction, linking, and query engine for Code System Graph.
Documentation
use serde::Deserialize;
use serde::de::DeserializeOwned;

use crate::ExtractionBudgets;

pub(crate) fn from_str<'de, T>(input: &'de str) -> Result<T, serde_saphyr::DeserializeError>
where
    T: Deserialize<'de>,
{
    serde_saphyr::from_str_with_options(
        input,
        serde_saphyr::options! {
            with_snippet: false,
        },
    )
}

pub(crate) fn from_multiple<T>(input: &str) -> Result<Vec<T>, serde_saphyr::DeserializeError>
where
    T: DeserializeOwned,
{
    serde_saphyr::from_multiple_with_options(
        input,
        serde_saphyr::options! {
            with_snippet: false,
        },
    )
}

pub(crate) fn from_str_with_extraction_budgets<'de, T>(
    input: &'de str,
    budgets: &ExtractionBudgets,
) -> Result<T, serde_saphyr::DeserializeError>
where
    T: Deserialize<'de>,
{
    let work = usize::try_from(budgets.max_work_units_per_artifact).unwrap_or(usize::MAX);
    let depth = usize::try_from(budgets.max_structural_depth_per_artifact).unwrap_or(usize::MAX);
    let scalar_bytes =
        usize::try_from(budgets.max_accumulated_string_bytes_per_artifact).unwrap_or(usize::MAX);
    let input_bytes = usize::try_from(budgets.max_input_bytes_per_artifact).unwrap_or(usize::MAX);
    let event_limit = work.saturating_mul(4);
    serde_saphyr::from_str_with_options(
        input,
        serde_saphyr::options! {
            with_snippet: false,
            budget: serde_saphyr::budget! {
                max_events: event_limit,
                max_aliases: work,
                max_anchors: work,
                max_depth: depth,
                max_inclusion_depth: 0,
                max_documents: 1,
                max_nodes: work,
                max_total_scalar_bytes: scalar_bytes,
                max_total_comment_bytes: input_bytes,
                max_merge_keys: work,
                enforce_alias_anchor_ratio: false,
            },
            alias_limits: serde_saphyr::alias_limits! {
                max_total_replayed_events: work,
                max_replay_stack_depth: depth,
                max_alias_expansions_per_anchor: work,
            },
        },
    )
}

#[cfg(test)]
mod tests {
    #[test]
    fn errors_do_not_include_source_snippets() {
        let input = "password: super-secret-value\ninvalid: [";
        let error = super::from_str::<serde_json::Value>(input).expect_err("invalid YAML");
        let message = error.to_string();

        assert!(!message.contains("super-secret-value"));
        assert!(!message.contains("password:"));
    }
}