1use alloc::{collections::BTreeMap, string::String, vec::Vec};
18#[cfg(not(feature = "std"))]
19use alloc::{format, string::ToString};
20use core::fmt::{Debug, Formatter, Write};
21
22use anyhow::Result;
23use risc0_core::field::Elem;
24
25use crate::core::digest::Digest;
26
27pub struct Reg {
29 pub offset: usize,
30}
31
32impl Component for Reg {
33 fn walk<V: Visitor>(&self, v: &mut V) -> core::fmt::Result {
34 v.visit_reg(self.offset)
35 }
36 fn ty_name(&self) -> &'static str {
37 "reg"
38 }
39}
40
41#[doc(hidden)]
45pub trait Component {
46 fn walk<V: Visitor>(&self, v: &mut V) -> core::fmt::Result;
47 fn ty_name(&self) -> &'static str;
48}
49
50impl<C: Component, const N: usize> Component for [&C; N] {
51 fn walk<V: Visitor>(&self, v: &mut V) -> core::fmt::Result {
52 for (n, elem) in self.iter().enumerate() {
53 let name = alloc::format!("[{n}]");
54 v.visit_component(&name, *elem)?;
55 }
56 Ok(())
57 }
58 fn ty_name(&self) -> &'static str {
59 "array"
60 }
61}
62
63#[doc(hidden)]
67pub trait Visitor {
68 fn visit_component(&mut self, name: &str, component: &impl Component) -> core::fmt::Result;
69 fn visit_reg(&mut self, offset: usize) -> core::fmt::Result;
70}
71
72#[derive(Clone, Copy)]
74pub struct Tree<'a, E: Elem + Into<u32>, C: Component> {
75 pub buf: &'a [E],
76 pub component: &'a C,
77}
78
79impl<'a, E: Elem + Into<u32>, C: Component> Tree<'a, E, C> {
80 pub fn new(buf: &'a [E], component: &'a C) -> Self {
82 Tree { buf, component }
83 }
84
85 pub fn map<SUBC: Component>(&self, f: impl FnOnce(&'a C) -> &'a SUBC) -> Tree<'a, E, SUBC> {
88 Tree {
89 buf: self.buf,
90 component: f(self.component),
91 }
92 }
93
94 pub fn get_u32s(&self) -> Result<Vec<u32>> {
96 let mut gather = TreeGather::new(self.buf);
97 self.component
98 .walk(&mut gather)
99 .map_err(anyhow::Error::msg)?;
100 Ok(gather.vals)
101 }
102
103 pub fn get_bytes(&self) -> Result<Vec<u8>> {
105 self.get_u32s()?
106 .into_iter()
107 .map(|val| u8::try_from(val).map_err(anyhow::Error::msg))
108 .collect()
109 }
110
111 pub fn get_shorts(&self) -> Result<Vec<u16>> {
113 self.get_u32s()?
114 .into_iter()
115 .map(|val| u16::try_from(val).map_err(anyhow::Error::msg))
116 .collect()
117 }
118
119 pub fn get_digest_from_shorts(&self) -> Result<Digest> {
121 let bytes: Vec<_> = self
122 .get_shorts()?
123 .into_iter()
124 .flat_map(|short| short.to_le_bytes())
125 .collect();
126 Digest::try_from(bytes.as_slice()).map_err(anyhow::Error::msg)
127 }
128
129 pub fn get_u32_from_bytes(&self) -> Result<u32> {
132 Ok(u32::from_le_bytes(
133 self.get_bytes()?
134 .as_slice()
135 .try_into()
136 .map_err(anyhow::Error::msg)?,
137 ))
138 }
139
140 pub fn get_u32_from_elem(&self) -> Result<u32> {
142 let u32s = self.get_u32s()?;
143 assert_eq!(u32s.len(), 1, "Expecting only a single u32 in {self:?}");
144 Ok(u32s[0])
145 }
146}
147
148pub fn get_elem<'a, E>(buf: &'a [E], reg: &Reg) -> &'a E {
150 buf.get(reg.offset).expect("Invalid offset in layout")
151}
152
153pub fn get_u32<E: Copy + Into<u32>>(buf: &[E], reg: &Reg) -> u32 {
155 (*get_elem(buf, reg)).into()
156}
157
158impl<E: Elem + Into<u32>, C: Component> Debug for Tree<'_, E, C> {
159 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
160 let mut p = TreePrinter::new(self.buf, Vec::new(), "top");
161 self.component.walk(&mut p)?;
162 for line in p.lines {
163 writeln!(f, "{line}")?;
164 }
165 Ok(())
166 }
167}
168
169struct TreePrinter<'a, E: Elem> {
172 buf: &'a [E],
173 lines: Vec<String>,
174 item_count: usize,
175 seen: BTreeMap<Vec<String>, String>,
176 path: Vec<&'a str>,
177}
178
179impl<'a, E: Elem> TreePrinter<'a, E> {
180 fn new(buf: &'a [E], mut path: Vec<&'a str>, name: &'a str) -> Self {
181 path.push(name);
182 TreePrinter {
183 buf,
184 lines: Vec::new(),
185 item_count: 0,
186 seen: BTreeMap::new(),
187 path,
188 }
189 }
190}
191
192impl<E: Elem + Into<u32>> Visitor for TreePrinter<'_, E> {
193 fn visit_component(&mut self, name: &str, component: &impl Component) -> core::fmt::Result {
194 match component.ty_name() {
195 "U32Reg" => {
196 let mut subtree = TreeGather::new(self.buf);
198 component.walk(&mut subtree)?;
199 if subtree.vals.iter().any(|&x| x != 0) {
200 let mut msg = format!("{name}: ");
201 write!(msg, " 0x")?;
202 for val in subtree.vals {
203 if val > 255 {
204 write!(msg, "[{val:#x}?]")?;
206 } else {
207 write!(msg, "{val:02x}")?;
208 }
209 }
210 self.lines.push(msg);
211 self.item_count += 1;
212 }
213 }
214 _ => {
215 let mut subtree = TreePrinter::new(self.buf, self.path.clone(), name);
217 component.walk(&mut subtree)?;
218 match subtree.item_count {
219 0 => {}
220 1 => {
221 self.item_count += 1;
225 let mut lines = subtree.lines;
226 lines[0] = format!("{name}: {{{}", lines[0]);
227 lines.last_mut().as_mut().unwrap().push_str(" }");
228 self.lines.extend(lines);
229 }
230 _ => {
231 self.item_count += 1;
234 match self.seen.get(&subtree.lines) {
235 Some(path) => {
236 self.lines.push(format!("{name}: duplicate of {path}"));
237 }
238 None => {
239 self.seen.extend(subtree.seen);
240 self.lines.push(format!("{name}: {{"));
241 self.lines
242 .extend(subtree.lines.iter().map(|s| format!(" {s}")));
243 self.lines.push("}".to_string());
244 self.seen.insert(subtree.lines, subtree.path.join("."));
245 }
246 }
247 }
248 }
249 }
250 }
251 Ok(())
252 }
253
254 fn visit_reg(&mut self, offset: usize) -> core::fmt::Result {
255 if let Some(val) = self.buf.get(offset) {
256 self.lines.push(format!("{val:?}"));
257 self.item_count += 1;
258 }
259 Ok(())
260 }
261}
262
263struct TreeGather<'a, E: Elem> {
265 buf: &'a [E],
266 vals: Vec<u32>,
267}
268
269impl<'a, E: Elem> TreeGather<'a, E> {
270 fn new(buf: &'a [E]) -> Self {
271 Self {
272 buf,
273 vals: Vec::new(),
274 }
275 }
276}
277
278impl<E: Elem + Into<u32>> Visitor for TreeGather<'_, E> {
279 fn visit_component(&mut self, _name: &str, component: &impl Component) -> core::fmt::Result {
280 component.walk(self)
281 }
282
283 fn visit_reg(&mut self, offset: usize) -> core::fmt::Result {
284 if let Some(val) = self.buf.get(offset) {
285 self.vals.push((*val).into())
286 }
287 Ok(())
288 }
289}