kernel/acpi/aml/
display.rs1use core::{
2 cell::RefCell,
3 fmt::{self, Write},
4};
5
6#[derive(Default)]
7struct PadAdapterState {
8 on_newline: bool,
9}
10
11struct PadAdapter<'buf, 'state> {
12 buf: &'buf mut (dyn fmt::Write + 'buf),
13 state: &'state mut PadAdapterState,
14}
15
16impl<'buf, 'state> PadAdapter<'buf, 'state> {
17 pub fn wrap(buf: &'buf mut dyn fmt::Write, state: &'state mut PadAdapterState) -> Self {
18 Self { buf, state }
19 }
20}
21
22impl fmt::Write for PadAdapter<'_, '_> {
23 fn write_str(&mut self, s: &str) -> fmt::Result {
24 for s in s.split_inclusive('\n') {
25 if self.state.on_newline {
26 self.buf.write_str(" ")?;
27 }
28
29 self.state.on_newline = s.ends_with('\n');
30 self.buf.write_str(s)?;
31 }
32
33 Ok(())
34 }
35
36 fn write_char(&mut self, c: char) -> fmt::Result {
37 if self.state.on_newline {
38 self.buf.write_str(" ")?;
39 }
40 self.state.on_newline = c == '\n';
41 self.buf.write_char(c)
42 }
43}
44
45struct FmtHolder<F>
46where
47 F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
48{
49 f: RefCell<Option<F>>,
50}
51
52impl<F> FmtHolder<F>
53where
54 F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
55{
56 fn new(value_fmt: F) -> Self {
57 Self {
58 f: RefCell::new(Some(value_fmt)),
59 }
60 }
61}
62
63impl<F> fmt::Display for FmtHolder<F>
64where
65 F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
66{
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 (self.f.borrow_mut().take().unwrap())(f)
69 }
70}
71
72pub struct AmlDisplayer<'a, 'b: 'a> {
73 fmt: &'a mut fmt::Formatter<'b>,
74 result: fmt::Result,
75 in_paren_arg: bool,
76 already_in_paren_arg: bool,
77 already_in_body: bool,
78 in_body: bool,
79 is_list: bool,
80}
81
82impl<'a, 'b: 'a> AmlDisplayer<'a, 'b> {
83 pub fn start(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> Self {
84 let result = fmt.write_str(name);
85 Self {
86 fmt,
87 result,
88 in_paren_arg: false,
89 already_in_paren_arg: false,
90 in_body: false,
91 is_list: false,
92 already_in_body: false,
93 }
94 }
95
96 pub fn set_list(&mut self, value: bool) -> &mut Self {
97 self.is_list = value;
98 self
99 }
100
101 pub fn paren_arg<F>(&mut self, value_fmt: F) -> &mut Self
102 where
103 F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
104 {
105 if !self.in_paren_arg && self.already_in_paren_arg {
106 self.result = Err(fmt::Error);
107 }
108
109 self.result = self.result.and_then(|_| {
110 let prefix = if self.in_paren_arg { ", " } else { " (" };
111
112 self.fmt.write_str(prefix)?;
113 value_fmt(self.fmt)
114 });
115
116 self.in_paren_arg = true;
117 self.already_in_paren_arg = true;
118
119 self
120 }
121
122 pub fn finish_paren_arg(&mut self) -> &mut Self {
123 if self.in_paren_arg {
124 self.result = self.result.and_then(|_| self.fmt.write_str(")"));
125 self.in_paren_arg = false;
126 }
127 self
128 }
129
130 pub fn body_field<F>(&mut self, value_fmt: F) -> &mut Self
131 where
132 F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
133 {
134 self.finish_paren_arg();
135
136 self.result = self.result.and_then(|_| {
137 if self.fmt.alternate() {
138 if !self.in_body {
139 self.fmt.write_str(" {\n")?;
140 } else {
141 self.fmt
142 .write_str(if self.is_list { ",\n" } else { "\n" })?;
143 }
144
145 let mut state = PadAdapterState { on_newline: true };
146 let mut writer = PadAdapter::wrap(self.fmt, &mut state);
147 let fmt_holder = FmtHolder::new(value_fmt);
148
149 writer.write_fmt(format_args!("{fmt_holder:#}"))
150 } else {
151 let prefix = if self.in_body {
152 if self.is_list {
153 ", "
154 } else {
155 "; "
156 }
157 } else {
158 " { "
159 };
160
161 self.fmt.write_str(prefix)?;
162 value_fmt(self.fmt)
163 }
164 });
165
166 self.in_body = true;
167 self.already_in_body = true;
168
169 self
170 }
171
172 pub fn at_least_empty_paren_arg(&mut self) -> &mut Self {
173 if !self.in_paren_arg && !self.already_in_paren_arg {
174 self.result = self.result.and_then(|_| self.fmt.write_str(" ()"));
175 }
176 self
177 }
178
179 pub fn at_least_empty_body(&mut self) -> &mut Self {
180 if !self.in_body && !self.already_in_body {
181 self.result = self.result.and_then(|_| self.fmt.write_str("{ }"));
182 }
183 self
184 }
185
186 pub fn finish(&mut self) -> fmt::Result {
187 self.finish_paren_arg();
188
189 if self.in_body {
190 self.result = self.result.and_then(|_| {
191 if !self.fmt.alternate() {
192 self.fmt.write_str(" }")
193 } else {
194 self.fmt.write_str("\n}")
195 }
196 });
197 self.in_body = false;
198 }
199
200 self.result
201 }
202}
203
204pub struct HexHolder<'a, T: fmt::UpperHex>(pub &'a T);
205
206impl<T: fmt::UpperHex> fmt::Display for HexHolder<'_, T> {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 write!(f, "{:#X}", self.0)
209 }
210}