1use crate::util::{read_str, read_u32le, read_u8};
2use crate::RpnExpr;
3use std::convert::TryInto;
4use std::fmt::{self, Display, Formatter};
5use std::io::{self, Read};
6
7#[derive(Debug)]
10pub struct Assertion {
11 source_file_id: u32,
12 line_no: u32,
13 offset: u32,
14 pc_section_id: u32,
15 pc_offset: u32,
16 err_type: AssertionType,
17 expr: RpnExpr,
18 message: Vec<u8>,
19}
20impl Assertion {
21 pub(crate) fn read_from(mut input: impl Read) -> Result<Self, io::Error> {
22 let source_file_id = read_u32le(&mut input)?;
23 let line_no = read_u32le(&mut input)?;
24 let offset = read_u32le(&mut input)?;
25 let pc_section_id = read_u32le(&mut input)?;
26 let pc_offset = read_u32le(&mut input)?;
27 let err_type = AssertionType::try_from(read_u8(&mut input)?)?;
28
29 let expr_size = read_u32le(&mut input)?.try_into().unwrap();
30 let mut expr = vec![0; expr_size];
31 input.read_exact(&mut expr)?;
32 let expr = RpnExpr::from_bytes(expr);
33 let message = read_str(input)?;
34
35 Ok(Self {
36 source_file_id,
37 line_no,
38 offset,
39 pc_section_id,
40 pc_offset,
41 err_type,
42 expr,
43 message,
44 })
45 }
46
47 pub fn source(&self) -> (u32, u32) {
50 (self.source_file_id, self.line_no)
51 }
52
53 pub fn offset(&self) -> u32 {
62 self.offset
63 }
64
65 pub fn err_type(&self) -> AssertionType {
67 self.err_type
68 }
69
70 pub fn pc_section_id(&self) -> u32 {
72 self.pc_section_id
73 }
74
75 pub fn pc_offset(&self) -> u32 {
80 self.pc_offset
81 }
82
83 pub fn expr(&self) -> &RpnExpr {
85 &self.expr
86 }
87
88 pub fn message(&self) -> &[u8] {
91 &self.message
92 }
93}
94
95#[derive(Debug, Clone, Copy)]
97pub enum AssertionType {
98 Warning,
100 Error,
102 Fatal,
104}
105impl AssertionType {
106 fn try_from(byte: u8) -> Result<Self, io::Error> {
107 use AssertionType::*;
108
109 Ok(match byte {
110 0 => Warning,
111 1 => Error,
112 2 => Fatal,
113 _ => {
114 return Err(io::Error::new(
115 io::ErrorKind::InvalidData,
116 "Invalid assertion type",
117 ))
118 }
119 })
120 }
121
122 pub fn name(&self) -> &'static str {
124 use AssertionType::*;
125
126 match self {
127 Warning => "warning",
128 Error => "error",
129 Fatal => "fatal",
130 }
131 }
132}
133impl Display for AssertionType {
134 fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
135 write!(fmt, "{}", self.name())
136 }
137}