Skip to main content

ferro_babe/
lib.rs

1mod decode;
2mod diagnostic;
3mod error;
4pub mod format;
5mod input;
6pub mod model;
7mod options;
8
9pub use diagnostic::{Diagnostic, DiagnosticSeverity, DiagnosticStage};
10pub use error::FerroBabeError;
11pub use format::{FerroFormatter, Formatter};
12pub use model::{Class, ClassVersion, Disassembly};
13pub use options::{DisassemblerBuilder, DisassemblerOptions, RecoveryMode};
14
15use decode::decode_class;
16use input::ClassHeader;
17use std::io::Read;
18
19#[derive(Debug, Clone, Default)]
20pub struct Disassembler {
21    options: DisassemblerOptions,
22}
23
24impl Disassembler {
25    #[must_use]
26    pub fn builder() -> DisassemblerBuilder {
27        DisassemblerBuilder::default()
28    }
29
30    #[must_use]
31    pub fn new(options: DisassemblerOptions) -> Self {
32        Self { options }
33    }
34
35    #[must_use]
36    pub fn options(&self) -> &DisassemblerOptions {
37        &self.options
38    }
39
40    pub fn parse(&self, bytes: &[u8]) -> Result<Disassembly, FerroBabeError> {
41        let header = ClassHeader::read(bytes)?;
42        match decode_class(bytes, header) {
43            Ok(class) => Ok(Disassembly::complete(class)),
44            Err(error) if self.options.recovery() == RecoveryMode::BestEffort => Ok(
45                Disassembly::partial(header.into(), vec![Diagnostic::from_decode_error(&error)]),
46            ),
47            Err(error) => Err(error),
48        }
49    }
50
51    pub fn parse_reader<R: Read>(&self, mut reader: R) -> Result<Disassembly, FerroBabeError> {
52        let mut bytes = Vec::new();
53        reader
54            .read_to_end(&mut bytes)
55            .map_err(|source| FerroBabeError::InputRead { source })?;
56        self.parse(&bytes)
57    }
58
59    pub fn disassemble(&self, bytes: &[u8]) -> Result<String, FerroBabeError> {
60        self.disassemble_with(bytes, &FerroFormatter)
61    }
62
63    pub fn disassemble_with<F: Formatter>(
64        &self,
65        bytes: &[u8],
66        formatter: &F,
67    ) -> Result<String, FerroBabeError> {
68        let disassembly = self.parse(bytes)?;
69        let class = disassembly
70            .class()
71            .ok_or(FerroBabeError::IncompleteDisassembly)?;
72        formatter.format(class)
73    }
74}