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}