1#![no_std]
2#![doc = include_str!("../README.md")]
3
4#[cfg(feature = "alloc")]
5extern crate alloc;
6
7use core::fmt::{self, Debug, Display};
8use core::hash::Hash;
9
10#[cfg(feature="use-serde")]
11#[macro_use] extern crate serde_derive;
12#[cfg(feature="use-serde")]
13use serde::{Serialize, Deserialize};
14
15mod address;
16pub use address::{Address, AddressBase, AddressDiff, AddressDiffAmount, AddressDisplay};
17pub use address::{AddressDisplayUsize, AddressDisplayU64, AddressDisplayU32, AddressDisplayU16};
18#[cfg(feature="address-parse")]
19pub use address::AddrParse;
20
21pub mod annotation;
22
23#[deprecated(since="0.3.0", note="yaxpeax_arch::color conflates output mechanism and styling, leaving it brittle and overly-restrictive. see `yaxpeax_arch::color_new`, which will replace `color` in a future version.")]
24mod color;
25#[allow(deprecated)] pub use color::{Colorize, NoColors, YaxColors};
27#[cfg(feature="color-new")]
28pub mod color_new;
29
30pub mod display;
31
32mod reader;
33pub use reader::{Reader, ReaderBuilder, ReadError, U8Reader, U16le, U16be, U32le, U32be, U64le, U64be};
34
35pub mod safer_unchecked;
36
37pub mod testkit;
38
39pub trait DecodeError: PartialEq + Display + Debug + Send + Sync + 'static {
45 fn data_exhausted(&self) -> bool;
47 fn bad_opcode(&self) -> bool;
55 fn bad_operand(&self) -> bool;
60 fn description(&self) -> &'static str;
62}
63
64#[derive(Debug, PartialEq, Eq, Copy, Clone)]
67pub enum StandardDecodeError {
68 ExhaustedInput,
69 InvalidOpcode,
70 InvalidOperand,
71}
72
73#[derive(Debug, PartialEq, Eq, Copy, Clone)]
77pub enum StandardPartialDecoderError {
78 ExhaustedInput,
79 InvalidOpcode,
80 InvalidOperand,
81 IncompleteDecoder,
82}
83
84#[cfg(feature = "std")]
85extern crate std;
86#[cfg(feature = "std")]
87impl std::error::Error for StandardDecodeError {
88 fn description(&self) -> &str {
89 <Self as DecodeError>::description(self)
90 }
91}
92#[cfg(feature = "std")]
93impl std::error::Error for StandardPartialDecoderError {
94 fn description(&self) -> &str {
95 <Self as DecodeError>::description(self)
96 }
97}
98
99impl fmt::Display for StandardDecodeError {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 f.write_str(self.description())
102 }
103}
104
105impl fmt::Display for StandardPartialDecoderError {
106 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107 f.write_str(self.description())
108 }
109}
110
111impl DecodeError for StandardDecodeError {
112 fn data_exhausted(&self) -> bool { *self == StandardDecodeError::ExhaustedInput }
113 fn bad_opcode(&self) -> bool { *self == StandardDecodeError::InvalidOpcode }
114 fn bad_operand(&self) -> bool { *self == StandardDecodeError::InvalidOperand }
115 fn description(&self) -> &'static str {
116 match self {
117 StandardDecodeError::ExhaustedInput => "exhausted input",
118 StandardDecodeError::InvalidOpcode => "invalid opcode",
119 StandardDecodeError::InvalidOperand => "invalid operand",
120 }
121 }
122}
123
124impl DecodeError for StandardPartialDecoderError {
125 fn data_exhausted(&self) -> bool { *self == StandardPartialDecoderError::ExhaustedInput }
126 fn bad_opcode(&self) -> bool { *self == StandardPartialDecoderError::InvalidOpcode }
127 fn bad_operand(&self) -> bool { *self == StandardPartialDecoderError::InvalidOperand }
128 fn description(&self) -> &'static str {
129 match self {
130 StandardPartialDecoderError::ExhaustedInput => "exhausted input",
131 StandardPartialDecoderError::InvalidOpcode => "invalid opcode",
132 StandardPartialDecoderError::InvalidOperand => "invalid operand",
133 StandardPartialDecoderError::IncompleteDecoder => "incomplete decoder",
134 }
135 }
136}
137
138pub trait Decoder<A: Arch + ?Sized> {
152 fn decode<T: Reader<A::Address, A::Word>>(&self, words: &mut T) -> Result<A::Instruction, A::DecodeError> {
155 let mut inst = A::Instruction::default();
156 self.decode_into(&mut inst, words).map(|_: ()| inst)
157 }
158
159 fn decode_into<T: Reader<A::Address, A::Word>>(&self, inst: &mut A::Instruction, words: &mut T) -> Result<(), A::DecodeError>;
169}
170
171#[cfg(feature = "use-serde")]
172pub trait AddressBounds: Address + Debug + Hash + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> {}
173#[cfg(not(feature = "use-serde"))]
174pub trait AddressBounds: Address + Debug + Hash + PartialEq + Eq {}
175
176#[cfg(feature = "use-serde")]
177impl<T> AddressBounds for T where T: Address + Debug + Hash + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> {}
178#[cfg(not(feature = "use-serde"))]
179impl<T> AddressBounds for T where T: Address + Debug + Hash + PartialEq + Eq {}
180
181#[cfg(feature = "std")]
182pub trait DecodeErrorBounds: std::error::Error + DecodeError {}
185#[cfg(feature = "std")]
186impl<T: std::error::Error + DecodeError> DecodeErrorBounds for T {}
187#[cfg(not(feature = "std"))]
188pub trait DecodeErrorBounds: DecodeError {}
191#[cfg(not(feature = "std"))]
192impl<T: DecodeError> DecodeErrorBounds for T {}
193
194
195pub trait Arch {
211 type Word: Debug + Display + PartialEq + Eq;
212 type Address: AddressBounds;
213 type Instruction: Instruction + LengthedInstruction<Unit=AddressDiff<Self::Address>> + Debug + Default + Sized;
214 type DecodeError: DecodeErrorBounds + Debug + Display;
215 type Decoder: Decoder<Self> + Default;
216 type Operand;
217}
218
219pub trait LengthedInstruction {
224 type Unit;
225 fn len(&self) -> Self::Unit;
229 fn min_size() -> Self::Unit;
234}
235
236pub trait Instruction {
237 fn well_defined(&self) -> bool;
238}
239
240#[allow(deprecated)]
241#[deprecated(since="0.3.0", note="ShowContextual ties YaxColors and fmt::Write in a way that only sometimes composes. simultaneously, it is too generic on Ctx, making it difficult to implement and use. it will be revisited in the future.")]
242pub trait ShowContextual<Addr, Ctx: ?Sized, T: fmt::Write, Y: YaxColors> {
243 fn contextualize(&self, colors: &Y, address: Addr, context: Option<&Ctx>, out: &mut T) -> fmt::Result;
244}
245
246