hotfix_dictionary/
layout.rs1use smartstring::alias::String as SmartString;
2use std::fmt;
3
4use crate::component::Component;
5use crate::{Dictionary, Field};
6
7pub fn display_layout_item(indent: u32, item: LayoutItem, f: &mut fmt::Formatter) -> fmt::Result {
8 for _ in 0..indent {
9 write!(f, " ")?;
10 }
11 match item.kind() {
12 LayoutItemKind::Field(_) => {
13 writeln!(
14 f,
15 "<field name='{}' required='{}' />",
16 item.tag_text(),
17 item.required(),
18 )?;
19 }
20 LayoutItemKind::Group(_, _fields) => {
21 writeln!(
22 f,
23 "<group name='{}' required='{}' />",
24 item.tag_text(),
25 item.required(),
26 )?;
27 writeln!(f, "</group>")?;
28 }
29 LayoutItemKind::Component(_c) => {
30 writeln!(
31 f,
32 "<component name='{}' required='{}' />",
33 item.tag_text(),
34 item.required(),
35 )?;
36 writeln!(f, "</component>")?;
37 }
38 }
39 Ok(())
40}
41
42#[derive(Clone, Debug)]
43pub(crate) enum LayoutItemKindData {
44 Component {
45 name: SmartString,
46 },
47 Group {
48 len_field_tag: u32,
49 items: Vec<LayoutItemData>,
50 },
51 Field {
52 tag: u32,
53 },
54}
55
56#[derive(Clone, Debug)]
57pub(crate) struct LayoutItemData {
58 pub(crate) required: bool,
59 pub(crate) kind: LayoutItemKindData,
60}
61
62fn layout_item_kind<'a>(item: &'a LayoutItemKindData, dict: &'a Dictionary) -> LayoutItemKind<'a> {
63 match item {
64 LayoutItemKindData::Component { name } => {
65 LayoutItemKind::Component(dict.component_by_name(name).unwrap())
66 }
67 LayoutItemKindData::Group {
68 len_field_tag,
69 items: items_data,
70 } => {
71 let items = items_data
72 .iter()
73 .map(|item_data| LayoutItem(dict, item_data))
74 .collect::<Vec<_>>();
75 let len_field = dict.field_by_tag(*len_field_tag).unwrap();
76 LayoutItemKind::Group(len_field, items)
77 }
78 LayoutItemKindData::Field { tag } => {
79 LayoutItemKind::Field(dict.field_by_tag(*tag).unwrap())
80 }
81 }
82}
83
84#[derive(Clone, Debug)]
86pub struct LayoutItem<'a>(pub(crate) &'a Dictionary, pub(crate) &'a LayoutItemData);
87
88#[derive(Debug)]
90pub enum LayoutItemKind<'a> {
91 Component(Component<'a>),
93 Group(Field<'a>, Vec<LayoutItem<'a>>),
95 Field(Field<'a>),
97}
98
99impl<'a> LayoutItem<'a> {
100 pub fn required(&self) -> bool {
103 self.1.required
104 }
105
106 pub fn kind(&self) -> LayoutItemKind<'_> {
108 layout_item_kind(&self.1.kind, self.0)
109 }
110
111 pub fn tag_text(&self) -> String {
113 match &self.1.kind {
114 LayoutItemKindData::Component { name } => {
115 self.0.component_by_name(name).unwrap().name().to_string()
116 }
117 LayoutItemKindData::Group {
118 len_field_tag,
119 items: _items,
120 } => self
121 .0
122 .field_by_tag(*len_field_tag)
123 .unwrap()
124 .name()
125 .to_string(),
126 LayoutItemKindData::Field { tag } => {
127 self.0.field_by_tag(*tag).unwrap().name().to_string()
128 }
129 }
130 }
131}
132
133pub(crate) type LayoutItems = Vec<LayoutItemData>;