vihaco_parser_core/container/
section.rs1use std::ops::Range;
5
6#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct SectionPath {
11 components: Vec<String>,
12}
13
14impl SectionPath {
15 pub fn root() -> Self {
16 Self {
17 components: Vec::new(),
18 }
19 }
20
21 pub fn is_root(&self) -> bool {
22 self.components.is_empty()
23 }
24
25 pub fn components(&self) -> &[String] {
26 &self.components
27 }
28
29 pub fn local_name(&self) -> Option<&str> {
30 self.components.last().map(String::as_str)
31 }
32
33 pub(crate) fn child(&self, local_name: impl Into<String>) -> Self {
34 let mut components = self.components.clone();
35 components.push(local_name.into());
36 Self { components }
37 }
38}
39
40impl Default for SectionPath {
41 fn default() -> Self {
42 Self::root()
43 }
44}
45
46impl std::fmt::Display for SectionPath {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 if self.is_root() {
49 return f.write_str("<root>");
50 }
51
52 for (index, component) in self.components.iter().enumerate() {
53 if index != 0 {
54 f.write_str("/")?;
55 }
56 f.write_str(component)?;
57 }
58 Ok(())
59 }
60}
61
62impl std::fmt::Debug for SectionPath {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 std::fmt::Display::fmt(self, f)
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct SectionNode {
71 pub path: SectionPath,
72 pub section: Range<usize>,
73 pub header: Range<usize>,
74 pub bytecode: Range<usize>,
75 pub children: Vec<SectionNode>,
76}
77
78pub(crate) fn validate_local_section_name(parent: &SectionPath, child: &str) -> eyre::Result<()> {
79 if child.is_empty() {
80 return Err(eyre::eyre!("section `{}` has an empty child name", parent));
81 }
82 if child.contains('/') {
83 return Err(eyre::eyre!(
84 "section `{}` child name `{}` must be a local name",
85 parent,
86 child
87 ));
88 }
89 Ok(())
90}