1use super::{DebugId, SymId};
4use crate::module::ModuleError;
5use crate::module::codec::{Decode, Encode, Reader, Writer};
6use crate::vocab::Pos;
7
8#[derive(Clone, Debug, Default, PartialEq, Eq)]
12pub struct Debug {
13 pub sources: Vec<SymId>,
14 pub positions: Vec<Pos>,
15 pub ops: Vec<Vec<DebugId>>,
16 pub statements: Vec<Vec<(u32, DebugId)>>,
17}
18
19impl Encode for Debug {
20 fn encode(&self, w: &mut Writer) {
21 self.sources.encode(w);
22 w.count(self.positions.len());
23 let mut last = Pos::default();
24 for &pos in &self.positions {
25 w.zigzag(i64::from(pos.file) - i64::from(last.file));
26 w.zigzag(i64::from(pos.line) - i64::from(last.line));
27 w.zigzag(i64::from(pos.col) - i64::from(last.col));
28 last = pos;
29 }
30 self.ops.encode(w);
31 self.statements.encode(w);
32 }
33}
34
35impl Decode for Debug {
36 fn decode(r: &mut Reader<'_>) -> Result<Self, ModuleError> {
37 let sources = Vec::decode(r)?;
38 let count = r.count()?;
39 let mut positions = Vec::with_capacity(count);
40 let mut last = Pos::default();
41 for _ in 0..count {
42 let pos = Pos {
43 file: moved(r, "file", last.file)?,
44 line: moved(r, "line", last.line)?,
45 col: moved(r, "column", last.col)?,
46 };
47 positions.push(pos);
48 last = pos;
49 }
50 let ops = Vec::decode(r)?;
51 let statements = Vec::decode(r)?;
52 Ok(Self { sources, positions, ops, statements })
53 }
54}
55
56fn moved<T: Into<i64> + TryFrom<i64>>(r: &mut Reader<'_>, what: &str, from: T) -> Result<T, ModuleError> {
57 let at = r.position();
58 let delta = r.zigzag()?;
59 let value = from.into().checked_add(delta);
60 value
61 .and_then(|v| T::try_from(v).ok())
62 .ok_or_else(|| r.malformed(at, format!("a {what} of {}", value.map_or_else(|| "over 64 bits".to_owned(), |v| v.to_string()))))
63}