rasn-compiler 0.1.0

An ASN.1 compiler producing bindings for the rasn framework
Documentation
use std::collections::BTreeMap;

use crate::intermediate::{constraints::*, error::*, *};

impl Constraint {
    pub(super) fn link_cross_reference(
        &mut self,
        identifier: &String,
        tlds: &BTreeMap<String, ToplevelDefinition>,
    ) -> Result<bool, GrammarError> {
        match self {
            Constraint::SubtypeConstraint(t) => t.set.link_cross_reference(identifier, tlds),
            _ => Ok(false),
        }
    }

    pub(super) fn has_cross_reference(&self) -> bool {
        if let Self::SubtypeConstraint(c) = self {
            c.set.has_cross_reference()
        } else {
            false
        }
    }
}

impl SubtypeElement {
    pub(super) fn link_cross_reference(
        &mut self,
        identifier: &String,
        tlds: &BTreeMap<String, ToplevelDefinition>,
    ) -> Result<bool, GrammarError> {
        match self {
            SubtypeElement::SingleValue {
                value,
                extensible: _,
            } => value.link_elsewhere_declared(identifier, tlds),
            SubtypeElement::PermittedAlphabet(e) => e.link_cross_reference(identifier, tlds),
            SubtypeElement::ContainedSubtype {
                subtype,
                extensible: _,
            } => subtype.link_subtype_constraint(tlds),
            SubtypeElement::ValueRange {
                min,
                max,
                extensible: _,
            } => {
                let a = min
                    .as_mut()
                    .map_or(Ok(false), |m| m.link_elsewhere_declared(identifier, tlds))?;
                let b = max
                    .as_mut()
                    .map_or(Ok(false), |m| m.link_elsewhere_declared(identifier, tlds))?;
                Ok(a || b)
            }
            SubtypeElement::SizeConstraint(s) => s.link_cross_reference(identifier, tlds),
            SubtypeElement::TypeConstraint(t) => t.link_constraint_reference(identifier, tlds),
            SubtypeElement::SingleTypeConstraint(s)
            | SubtypeElement::MultipleTypeConstraints(s) => s
                .constraints
                .iter_mut()
                .flat_map(|cc| &mut cc.constraints)
                .try_fold(false, |acc, b| {
                    b.link_cross_reference(identifier, tlds)
                        .map(|res| res || acc)
                }),
            _ => Ok(false),
        }
    }

    pub(super) fn has_cross_reference(&self) -> bool {
        match self {
            SubtypeElement::SingleValue {
                value,
                extensible: _,
            } => value.is_elsewhere_declared(),
            SubtypeElement::PatternConstraint(_) => false,
            SubtypeElement::UserDefinedConstraint(_) => false,
            SubtypeElement::PropertySettings(_) => false,
            SubtypeElement::PermittedAlphabet(e) => e.has_cross_reference(),
            SubtypeElement::ContainedSubtype {
                subtype,
                extensible: _,
            } => subtype.contains_constraint_reference(),
            SubtypeElement::ValueRange {
                min,
                max,
                extensible: _,
            } => {
                min.as_ref().map_or(false, |s| s.is_elsewhere_declared())
                    || max.as_ref().map_or(false, |s| s.is_elsewhere_declared())
            }
            SubtypeElement::SizeConstraint(s) => s.has_cross_reference(),
            SubtypeElement::TypeConstraint(t) => t.references_class_by_name(),
            SubtypeElement::MultipleTypeConstraints(s)
            | SubtypeElement::SingleTypeConstraint(s) => s
                .constraints
                .iter()
                .any(|cc| cc.constraints.iter().any(|c| c.has_cross_reference())),
        }
    }
}

impl ElementOrSetOperation {
    pub(super) fn link_cross_reference(
        &mut self,
        identifier: &String,
        tlds: &BTreeMap<String, ToplevelDefinition>,
    ) -> Result<bool, GrammarError> {
        match self {
            ElementOrSetOperation::Element(e) => e.link_cross_reference(identifier, tlds),
            ElementOrSetOperation::SetOperation(s) => {
                let a = s.base.link_cross_reference(identifier, tlds)?;
                let b = s.operant.link_cross_reference(identifier, tlds)?;
                Ok(a || b)
            }
        }
    }

    pub(super) fn has_cross_reference(&self) -> bool {
        match self {
            ElementOrSetOperation::Element(e) => e.has_cross_reference(),
            ElementOrSetOperation::SetOperation(s) => {
                s.base.has_cross_reference() || s.operant.has_cross_reference()
            }
        }
    }
}