fluidattacks-blends-domain 0.6.1

Blends functional core: pure AST graph to syntax graph (no_std)
Documentation
//! The reader signature and the mutable context threaded through the walk.

use alloc::borrow::ToOwned;

use crate::ast::AstGraph;
use crate::syntax::dispatchers::Dispatcher;
use crate::syntax::fields::{OptionalField, RequiredField};
use crate::syntax::readers::common::missing_node;
use crate::syntax::{SyntaxGraph, SyntaxGraphError, SyntaxMetadata};
use crate::{CodeGraph, Language, NodeId};

pub type SyntaxReader =
    fn(args: &mut SyntaxGraphArgs<'_>, n_id: NodeId) -> Result<Option<NodeId>, SyntaxGraphError>;

pub struct SyntaxGraphArgs<'a> {
    pub language: Language,
    pub ast_graph: &'a AstGraph,
    pub syntax_graph: &'a mut SyntaxGraph,
    pub metadata: &'a mut SyntaxMetadata,
    pub dispatcher: Dispatcher,
}

impl<'a> SyntaxGraphArgs<'a> {
    #[must_use]
    pub fn new(
        language: Language,
        ast_graph: &'a AstGraph,
        syntax_graph: &'a mut SyntaxGraph,
        metadata: &'a mut SyntaxMetadata,
        dispatcher: Dispatcher,
    ) -> Self {
        Self {
            language,
            ast_graph,
            syntax_graph,
            metadata,
            dispatcher,
        }
    }

    pub fn generic(&mut self, n_id: NodeId) -> Result<NodeId, SyntaxGraphError> {
        let ast_graph = self.ast_graph;
        let node_type = ast_graph
            .label_type(n_id)
            .ok_or(SyntaxGraphError::MissingAstNode)?;

        let built = match (self.dispatcher)(node_type) {
            Some(reader) => reader(self, n_id)?,
            None => None,
        };

        built.map_or_else(
            || missing_node::reader(self, n_id, node_type.to_owned()),
            Ok,
        )
    }

    #[must_use]
    pub fn optional_field_alt<F: OptionalField>(&self, n_id: NodeId, key: F) -> Option<NodeId> {
        self.ast_graph
            .nodes
            .get(&n_id)
            .and_then(|node| node.fields.get(key.name()).copied())
    }

    pub fn required_field_alt<F: RequiredField>(
        &self,
        n_id: NodeId,
        key: F,
    ) -> Result<NodeId, SyntaxGraphError> {
        self.ast_graph
            .nodes
            .get(&n_id)
            .ok_or(SyntaxGraphError::MissingAstNode)?
            .fields
            .get(key.name())
            .copied()
            .ok_or(SyntaxGraphError::UnexpectedAstShape)
    }
}