kernel/acpi/aml/
display.rs

1use 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}