dbc_rs/nodes/mod.rs
1mod impls;
2mod parse;
3#[cfg(feature = "std")]
4mod std;
5mod validate;
6
7#[cfg(feature = "std")]
8mod builder;
9
10use crate::{
11 MAX_NODES,
12 compat::{Comment, Name, Vec},
13};
14#[cfg(feature = "std")]
15pub use builder::NodesBuilder;
16
17/// Represents a single node (ECU) with its name and optional comment.
18#[derive(Debug, Default, PartialEq, Eq, Hash, Clone)]
19pub struct Node {
20 name: Name,
21 comment: Option<Comment>,
22}
23
24impl Node {
25 /// Creates a new node with the given name and no comment.
26 #[inline]
27 pub(crate) fn new(name: Name) -> Self {
28 Self {
29 name,
30 comment: None,
31 }
32 }
33
34 /// Creates a new node with the given name and comment.
35 #[inline]
36 #[cfg(feature = "std")]
37 pub(crate) fn with_comment(name: Name, comment: Option<Comment>) -> Self {
38 Self { name, comment }
39 }
40
41 /// Returns the node name.
42 #[inline]
43 #[must_use = "return value should be used"]
44 pub fn name(&self) -> &str {
45 self.name.as_str()
46 }
47
48 /// Returns the node comment, if any.
49 #[inline]
50 #[must_use = "return value should be used"]
51 pub fn comment(&self) -> Option<&str> {
52 self.comment.as_ref().map(|c| c.as_str())
53 }
54
55 /// Sets the comment for this node.
56 #[inline]
57 pub(crate) fn set_comment(&mut self, comment: Comment) {
58 self.comment = Some(comment);
59 }
60}
61
62type InnerNodes = Vec<Node, { MAX_NODES }>;
63
64/// Represents a collection of node (ECU) names from a DBC file.
65///
66/// The `BU_` statement in a DBC file lists all nodes (ECUs) on the CAN bus.
67/// This struct stores the node names as borrowed references.
68///
69/// # Examples
70///
71/// ```rust,no_run
72/// use dbc_rs::Dbc;
73///
74/// let dbc = Dbc::parse(r#"VERSION "1.0"
75///
76/// BU_: ECM TCM BCM
77///
78/// BO_ 256 Engine : 8 ECM
79/// SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm"
80/// "#)?;
81///
82/// // Access nodes
83/// assert_eq!(dbc.nodes().len(), 3);
84/// assert!(dbc.nodes().contains("ECM"));
85/// assert!(dbc.nodes().contains("TCM"));
86///
87/// // Iterate over nodes
88/// for node in dbc.nodes().iter() {
89/// println!("Node: {}", node);
90/// }
91/// # Ok::<(), dbc_rs::Error>(())
92/// ```
93///
94/// # Empty Nodes
95///
96/// A DBC file may have an empty node list (`BU_:` with no nodes):
97///
98/// ```rust,no_run
99/// use dbc_rs::Dbc;
100///
101/// let dbc = Dbc::parse(r#"VERSION "1.0"
102///
103/// BU_:
104///
105/// BO_ 256 Engine : 8 ECM
106/// "#)?;
107///
108/// assert!(dbc.nodes().is_empty());
109/// # Ok::<(), dbc_rs::Error>(())
110/// ```
111///
112/// # DBC Format
113///
114/// In DBC files, nodes are specified on the `BU_` line:
115/// - Format: `BU_: Node1 Node2 Node3 ...`
116/// - Node names are space-separated
117/// - Maximum of 256 nodes (DoS protection)
118/// - All node names must be unique (case-sensitive)
119/// - Empty node list is valid (`BU_:`)
120/// - Maximum 32 characters per node name by default
121#[derive(Debug, Default, PartialEq, Eq, Hash, Clone)]
122pub struct Nodes {
123 nodes: InnerNodes,
124}