ginko 0.0.6

A device-tree source parser and analyzer
Documentation
use crate::dts::ast::{
    AnyDirective, Cell, DtsFile, Include, Node, NodePayload, Primary, Property, PropertyValue,
    Reference, ReferencedNode, WithToken,
};
use crate::dts::{HasSpan, NodeItem, Position};

#[allow(unused)]
pub enum ItemAtCursor<'a> {
    Property(&'a Property),
    Node(&'a Node),
    Reference(&'a Reference),
    Label(&'a WithToken<String>),
    Include(&'a Include),
}

impl DtsFile {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        for element in &self.elements {
            if let Some(item) = element.item_at_cursor(cursor) {
                return Some(item);
            }
        }
        None
    }
}

impl Primary {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        match self {
            Primary::Directive(directive) => directive.item_at_cursor(cursor),
            Primary::Root(root) => root.item_at_cursor(cursor),
            Primary::ReferencedNode(node) => node.item_at_cursor(cursor),
            Primary::CStyleInclude(_) => None,
        }
    }
}

impl AnyDirective {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        match self {
            AnyDirective::Include(include) => {
                if include.span().contains(cursor) {
                    Some(ItemAtCursor::Include(include))
                } else {
                    None
                }
            }
            AnyDirective::DeletedNode(_, node_ref) => {
                Some(ItemAtCursor::Reference(node_ref.item()))
            }
            AnyDirective::OmitIfNoRef(_, node_ref) => {
                Some(ItemAtCursor::Reference(node_ref.item()))
            }
            _ => None,
        }
    }
}

impl ReferencedNode {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        if self.reference.span().contains(cursor) {
            return Some(ItemAtCursor::Reference(self.reference.item()));
        }
        self.payload.item_at_cursor(cursor)
    }
}

impl Node {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        if let Some(label) = &self.label {
            if label.span().contains(cursor) {
                return Some(ItemAtCursor::Label(label));
            }
        }
        self.payload.item_at_cursor(cursor)
    }
}

impl NodePayload {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        for node in &self.items {
            if let Some(item) = node.item_at_cursor(cursor) {
                return Some(item);
            }
        }
        None
    }
}

impl NodeItem {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        match self {
            NodeItem::Property(property) => property.item_at_cursor(cursor),
            NodeItem::Node(node) => node.item_at_cursor(cursor),
            NodeItem::DeletedNode(..) => None,
            NodeItem::DeletedProperty(..) => None,
        }
    }
}

impl Property {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        if let Some(label) = &self.label {
            if label.span().contains(cursor) {
                return Some(ItemAtCursor::Label(label));
            }
        }
        for value in &self.values {
            if let Some(item) = value.item_at_cursor(cursor) {
                return Some(item);
            }
        }
        None
    }
}

impl PropertyValue {
    pub fn item_at_cursor(&self, cursor: &Position) -> Option<ItemAtCursor<'_>> {
        match self {
            PropertyValue::String(_) => None,
            PropertyValue::Cells(_, cells, _) => {
                for cell in cells {
                    match cell {
                        Cell::Number(_) | Cell::Expression => {}
                        Cell::Reference(reference) => {
                            if reference.span().contains(cursor) {
                                return Some(ItemAtCursor::Reference(reference.item()));
                            }
                        }
                    }
                }
                None
            }
            PropertyValue::Reference(reference) => {
                if reference.span().contains(cursor) {
                    Some(ItemAtCursor::Reference(reference.item()))
                } else {
                    None
                }
            }
            PropertyValue::ByteStrings(..) => None,
        }
    }
}