diff options
author | iximeow <me@iximeow.net> | 2020-01-15 01:14:50 -0800 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2020-01-15 01:14:50 -0800 |
commit | 894cba0dde913d86472430eae8b7ba0353711b4e (patch) | |
tree | 3c0f4eea33a8c0c1db60a1d843cd72702a7be633 | |
parent | f0869a1e2fbbdc50f6b020f088da020463e177da (diff) |
no_std!!
this makes yaxpeax-arch no_std. generally nothing has changed w.r.t
downstream crates, but a lot to do with colorization has been moved
tweaked to make it no_std-friendly (specifically, allowing `termion` to
be an optional dependency)
this also makes address parsing optional, in the hopes that decode-only
use cases don't need to involve as much machinery when building.
-rw-r--r-- | Cargo.toml | 14 | ||||
-rw-r--r-- | src/address/mod.rs | 163 | ||||
-rw-r--r-- | src/color.rs | 386 | ||||
-rw-r--r-- | src/display.rs | 151 | ||||
-rw-r--r-- | src/lib.rs | 498 |
5 files changed, 666 insertions, 546 deletions
@@ -10,16 +10,20 @@ repository = "https://git.iximeow.net/yaxpeax-arch/" version = "0.0.1" [dependencies] -"num-traits" = "0.2" -"termion" = "1.4.0" -"serde" = "1.0" +"num-traits" = { version = "0.2", default-features = false } +"termion" = { version = "1.4.0", optional = true } +"serde" = { version = "1.0", optional = true } [profile.release] lto = true [features] -default = [] +default = ["use-serde", "colors", "address-parse"] # enables the (optional) use of Serde for bounds on # Arch and Arch::Address -use-serde = [] +use-serde = ["serde"] + +colors = ["termion"] + +address-parse = [] diff --git a/src/address/mod.rs b/src/address/mod.rs new file mode 100644 index 0000000..7146d01 --- /dev/null +++ b/src/address/mod.rs @@ -0,0 +1,163 @@ +use core::hash::Hash; + +use core::fmt::{self, Debug, Display, Formatter}; + +use core::ops::{Add, Sub, AddAssign, SubAssign}; + +use num_traits::identities; +use num_traits::{Bounded, WrappingAdd, WrappingSub, CheckedAdd, CheckedSub}; + +#[cfg(feature="use-serde")] +use serde::{Deserialize, Serialize}; + +pub trait AddressBase where Self: + Debug + Display + AddressDisplay + + Copy + Clone + Sized + Hash + + Ord + Eq + PartialEq + Bounded + + Add<Output=Self> + Sub<Output=Self> + + AddAssign + SubAssign + + WrappingAdd + WrappingSub + + CheckedAdd + CheckedSub + + Hash + + identities::One + identities::Zero { + fn to_linear(&self) -> usize; +} + +#[cfg(all(feature="use-serde", feature="address-parse"))] +pub trait Address where Self: + AddressBase + + Serialize + for<'de> Deserialize<'de> + + AddrParse { +} + +#[cfg(all(feature="use-serde", not(feature="address-parse")))] +pub trait Address where Self: + AddressBase + + Serialize + for<'de> Deserialize<'de> { +} + +#[cfg(all(not(feature="use-serde"), feature="address-parse"))] +pub trait Address where Self: + AddressBase + AddrParse { +} + +#[cfg(all(not(feature="use-serde"), not(feature="address-parse")))] +pub trait Address where Self: AddressBase { } + +impl AddressBase for u16 { + fn to_linear(&self) -> usize { *self as usize } +} + +impl Address for u16 {} + +impl AddressBase for u32 { + fn to_linear(&self) -> usize { *self as usize } +} + +impl Address for u32 {} + +impl AddressBase for u64 { + fn to_linear(&self) -> usize { *self as usize } +} + +impl Address for u64 {} + +impl AddressBase for usize { + fn to_linear(&self) -> usize { *self } +} + +impl Address for usize {} + +pub trait AddressDisplay { + fn show(&self, f: &mut Formatter) -> fmt::Result; +} + +impl AddressDisplay for usize { + fn show(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:#x}", self) + } +} + +impl AddressDisplay for u64 { + fn show(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:#x}", self) + } +} + +impl AddressDisplay for u32 { + fn show(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:#x}", self) + } +} + +impl AddressDisplay for u16 { + fn show(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:#x}", self) + } +} + +/* + * TODO: this should be FromStr. + * that would require newtyping address primitives, though + * + * this is not out of the question, BUT is way more work than + * i want to put in right now + * + * this is one of those "clean it up later" situations + */ +#[cfg(feature="address-parse")] +use core::str::FromStr; + +#[cfg(feature="address-parse")] +pub trait AddrParse: Sized { + type Err; + fn parse_from(s: &str) -> Result<Self, Self::Err>; +} + +#[cfg(feature="address-parse")] +impl AddrParse for usize { + type Err = core::num::ParseIntError; + fn parse_from(s: &str) -> Result<Self, Self::Err> { + if s.starts_with("0x") { + usize::from_str_radix(&s[2..], 16) + } else { + usize::from_str(s) + } + } +} + +#[cfg(feature="address-parse")] +impl AddrParse for u64 { + type Err = core::num::ParseIntError; + fn parse_from(s: &str) -> Result<Self, Self::Err> { + if s.starts_with("0x") { + u64::from_str_radix(&s[2..], 16) + } else { + u64::from_str(s) + } + } +} + +#[cfg(feature="address-parse")] +impl AddrParse for u32 { + type Err = core::num::ParseIntError; + fn parse_from(s: &str) -> Result<Self, Self::Err> { + if s.starts_with("0x") { + u32::from_str_radix(&s[2..], 16) + } else { + u32::from_str(s) + } + } +} + +#[cfg(feature="address-parse")] +impl AddrParse for u16 { + type Err = core::num::ParseIntError; + fn parse_from(s: &str) -> Result<Self, Self::Err> { + if s.starts_with("0x") { + u16::from_str_radix(&s[2..], 16) + } else { + u16::from_str(s) + } + } +} diff --git a/src/color.rs b/src/color.rs new file mode 100644 index 0000000..4bcbd15 --- /dev/null +++ b/src/color.rs @@ -0,0 +1,386 @@ +use core::fmt::{self, Display, Formatter}; + +pub enum Colored<T: Display, Colorer: Display> { + Color(T, Colorer, Colorer), + Just(T) +} + +impl <T: Display, Colorer: Display> Display for Colored<T, Colorer> { + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + match self { + Colored::Color(t, before, after) => { + write!(fmt, "{}{}{}", before, t, after) + }, + Colored::Just(t) => { + write!(fmt, "{}", t) + } + } + } +} + +pub trait YaxColors<Color: Display> { + fn arithmetic_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn stack_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn nop_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn stop_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn control_flow_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn data_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn comparison_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn invalid_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn platform_op<T: Display>(&self, t: T) -> Colored<T, Color>; + fn misc_op<T: Display>(&self, t: T) -> Colored<T, Color>; + + fn register<T: Display>(&self, t: T) -> Colored<T, Color>; + fn program_counter<T: Display>(&self, t: T) -> Colored<T, Color>; + fn number<T: Display>(&self, t: T) -> Colored<T, Color>; + fn zero<T: Display>(&self, t: T) -> Colored<T, Color>; + fn one<T: Display>(&self, t: T) -> Colored<T, Color>; + fn minus_one<T: Display>(&self, t: T) -> Colored<T, Color>; + fn address<T: Display>(&self, t: T) -> Colored<T, Color>; + fn symbol<T: Display>(&self, t: T) -> Colored<T, Color>; + fn function<T: Display>(&self, t: T) -> Colored<T, Color>; +} + +pub struct NoColors; + +impl YaxColors<&'static str> for NoColors { + fn arithmetic_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn stack_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn nop_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn stop_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn control_flow_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn data_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn comparison_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn invalid_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn platform_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn misc_op<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn register<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn program_counter<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn number<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn zero<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn one<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn minus_one<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn address<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn symbol<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } + fn function<T: Display>(&self, t: T) -> Colored<T, &'static str> { + Colored::Just(t) + } +} + +pub trait Colorize<T: fmt::Write, Color: Display, Y: YaxColors<Color> + ?Sized> { + fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result; +} + +#[cfg(feature="colors")] +pub use termion_color::ColorSettings; + +#[cfg(feature="colors")] +mod termion_color { + use core::fmt::Display; + + use termion::color; + use serde::Serialize; + + use crate::color::{Colored, YaxColors}; + + #[cfg(feature="use-serde")] + impl Serialize for ColorSettings { + fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + use serde::ser::SerializeStruct; + let s = serializer.serialize_struct("ColorSettings", 0)?; + s.end() + } + } + + pub struct ColorSettings { + arithmetic: color::Fg<&'static dyn color::Color>, + stack: color::Fg<&'static dyn color::Color>, + nop: color::Fg<&'static dyn color::Color>, + stop: color::Fg<&'static dyn color::Color>, + control: color::Fg<&'static dyn color::Color>, + data: color::Fg<&'static dyn color::Color>, + comparison: color::Fg<&'static dyn color::Color>, + invalid: color::Fg<&'static dyn color::Color>, + platform: color::Fg<&'static dyn color::Color>, + misc: color::Fg<&'static dyn color::Color>, + + register: color::Fg<&'static dyn color::Color>, + program_counter: color::Fg<&'static dyn color::Color>, + + number: color::Fg<&'static dyn color::Color>, + zero: color::Fg<&'static dyn color::Color>, + one: color::Fg<&'static dyn color::Color>, + minus_one: color::Fg<&'static dyn color::Color>, + + function: color::Fg<&'static dyn color::Color>, + symbol: color::Fg<&'static dyn color::Color>, + address: color::Fg<&'static dyn color::Color>, + } + + #[cfg(feature="colorize")] + impl Default for ColorSettings { + fn default() -> ColorSettings { + ColorSettings { + arithmetic: color::Fg(&color::LightYellow), + stack: color::Fg(&color::Magenta), + nop: color::Fg(&color::Blue), + stop: color::Fg(&color::LightRed), + control: color::Fg(&color::Green), + data: color::Fg(&color::LightMagenta), + comparison: color::Fg(&color::Yellow), + invalid: color::Fg(&color::Red), + platform: color::Fg(&color::Cyan), + misc: color::Fg(&color::LightCyan), + + register: color::Fg(&color::Cyan), + program_counter: color::Fg(&color::Red), + + number: color::Fg(&color::White), + zero: color::Fg(&color::White), + one: color::Fg(&color::White), + minus_one: color::Fg(&color::White), + + function: color::Fg(&color::LightGreen), + symbol: color::Fg(&color::LightGreen), + address: color::Fg(&color::Green), + } + } + } + + impl YaxColors<color::Fg<&'static dyn color::Color>> for ColorSettings { + fn arithmetic_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.arithmetic, color::Fg(&color::Reset)) + } + fn stack_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.stack, color::Fg(&color::Reset)) + } + fn nop_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.nop, color::Fg(&color::Reset)) + } + fn stop_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.stop, color::Fg(&color::Reset)) + } + fn control_flow_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.control, color::Fg(&color::Reset)) + } + fn data_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.data, color::Fg(&color::Reset)) + } + fn comparison_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.comparison, color::Fg(&color::Reset)) + } + fn invalid_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.invalid, color::Fg(&color::Reset)) + } + fn misc_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.misc, color::Fg(&color::Reset)) + } + fn platform_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.platform, color::Fg(&color::Reset)) + } + + fn register<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.register, color::Fg(&color::Reset)) + } + fn program_counter<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.program_counter, color::Fg(&color::Reset)) + } + fn number<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.number, color::Fg(&color::Reset)) + } + fn zero<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.zero, color::Fg(&color::Reset)) + } + fn one<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.one, color::Fg(&color::Reset)) + } + fn minus_one<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.minus_one, color::Fg(&color::Reset)) + } + fn address<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.address, color::Fg(&color::Reset)) + } + fn symbol<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.symbol, color::Fg(&color::Reset)) + } + fn function<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + Colored::Color(t, self.function, color::Fg(&color::Reset)) + } + } + + impl <'a> YaxColors<color::Fg<&'static dyn color::Color>>for Option<&'a ColorSettings> { + fn arithmetic_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.arithmetic_op(t) } + None => { Colored::Just(t) } + } + } + fn stack_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.stack_op(t) } + None => { Colored::Just(t) } + } + } + fn nop_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.nop_op(t) } + None => { Colored::Just(t) } + } + } + fn stop_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.stop_op(t) } + None => { Colored::Just(t) } + } + } + fn control_flow_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.control_flow_op(t) } + None => { Colored::Just(t) } + } + } + fn data_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.data_op(t) } + None => { Colored::Just(t) } + } + } + fn comparison_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.comparison_op(t) } + None => { Colored::Just(t) } + } + } + fn invalid_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.invalid_op(t) } + None => { Colored::Just(t) } + } + } + fn misc_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.misc_op(t) } + None => { Colored::Just(t) } + } + } + fn platform_op<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.platform_op(t) } + None => { Colored::Just(t) } + } + } + + fn register<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.register(t) } + None => { Colored::Just(t) } + } + } + fn program_counter<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.program_counter(t) } + None => { Colored::Just(t) } + } + } + fn number<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.number(t) } + None => { Colored::Just(t) } + } + } + fn zero<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.zero(t) } + None => { Colored::Just(t) } + } + } + fn one<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.one(t) } + None => { Colored::Just(t) } + } + } + fn minus_one<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.minus_one(t) } + None => { Colored::Just(t) } + } + } + fn address<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.address(t) } + None => { Colored::Just(t) } + } + } + fn symbol<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.symbol(t) } + None => { Colored::Just(t) } + } + } + fn function<T: Display>(&self, t: T) -> Colored<T, color::Fg<&'static dyn color::Color>> { + match self { + Some(colors) => { colors.function(t) } + None => { Colored::Just(t) } + } + } + } +} + +/* + * can this be a derivable trait or something? + */ +/* +impl <T: Colorize> Display for T { + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + self.colorize(None, fmt) + } +} +*/ + +/* + * and make this auto-derive from a ShowContextual impl? + */ +/* +impl <T, U> Colorize for T where T: ShowContextual<Ctx=U> { + fn colorize(&self, colors: Option<&ColorSettings>, fmt: &mut Formatter) -> fmt::Result { + self.contextualize(colors, None, fmt) + } +} +*/ diff --git a/src/display.rs b/src/display.rs index 5ba9cd1..50d63d5 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,3 +1,9 @@ +use crate::YaxColors; + +use core::fmt; +use core::num::Wrapping; +use core::ops::Neg; + pub enum NumberStyleHint { Signed, HexSigned, @@ -11,105 +17,120 @@ pub enum NumberStyleHint { HexUnsignedWithSign } -pub fn format_number_i32(i: i32, hint: NumberStyleHint) -> String { +pub fn format_number_i32<W: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>>(colors: &Y, f: &mut W, i: i32, hint: NumberStyleHint) -> fmt::Result { match hint { NumberStyleHint::Signed => { - format!("{}", i) + write!(f, "{}", colors.number(i)) }, NumberStyleHint::HexSigned => { - if i == std::i32::MIN { - format!("-0x7fffffff") - } else if i < 0 { - format!("-{:#x}", -i) - } else { - format!("{:#x}", i) - } + write!(f, "{}", colors.number(signed_i32_hex(i))) }, NumberStyleHint::Unsigned => { - format!("{}", i as u32) + write!(f, "{}", colors.number(i as u32)) }, NumberStyleHint::HexUnsigned => { - format!("{:#x}", i as u32) + write!(f, "{}", colors.number(u32_hex(i as u32))) }, NumberStyleHint::SignedWithSignSplit => { - if i == std::i32::MIN { - format!("- 2147483647") + if i == core::i32::MIN { + write!(f, "- {}", colors.number("2147483647")) } else if i < 0 { - format!("- {}", -i) + write!(f, "- {}", colors.number(-Wrapping(i))) } else { - format!("+ {}", i) + write!(f, "+ {}", colors.number(i)) } } NumberStyleHint::HexSignedWithSignSplit => { - if i == std::i32::MIN { - format!("- 0x7fffffff") + if i == core::i32::MIN { + write!(f, "- {}", colors.number("0x7fffffff")) } else if i < 0 { - format!("- {:#x}", -i) + write!(f, "- {}", colors.number(u32_hex((-Wrapping(i)).0 as u32))) } else { - format!("+ {:#x}", i) + write!(f, "+ {}", colors.number(u32_hex(i as u32))) } }, NumberStyleHint::HexSignedWithSign => { - if i == std::i32::MIN { - format!("-0x7fffffff") - } else if i < 0 { - format!("-{:#x}", -i) - } else { - format!("+{:#x}", i) - } + write!(f, "{}", signed_i32_hex(i)) }, NumberStyleHint::SignedWithSign => { - format!("{:+}", i) + write!(f, "{:+}", i) } NumberStyleHint::HexUnsignedWithSign => { - format!("{:+#x}", i as u32) + write!(f, "{:+#x}", i as u32) }, NumberStyleHint::UnsignedWithSign => { - format!("{:+}", i as u32) + write!(f, "{:+}", i as u32) } } } -pub fn signed_i8_hex(imm: i8) -> String { - let (sign, imm) = if imm == std::i8::MIN { - (false, imm) - } else if imm < 0 { - (true, -imm) - } else { - (false, imm) - }; - format!("{}{:#x}", if sign { "-" } else { "" } , imm) +pub struct SignedHexDisplay<T: core::fmt::LowerHex + Neg> { + value: T, + negative: bool +} + +impl<T: fmt::LowerHex + Neg + Copy> fmt::Display for SignedHexDisplay<T> where Wrapping<T>: Neg, <Wrapping<T> as Neg>::Output: fmt::LowerHex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.negative { + write!(f, "-{:#x}", -Wrapping(self.value)) + } else { + write!(f, "{:#x}", self.value) + } + } +} + +pub fn u8_hex(value: u8) -> SignedHexDisplay<i8> { + SignedHexDisplay { + value: value as i8, + negative: false, + } +} + +pub fn signed_i8_hex(imm: i8) -> SignedHexDisplay<i8> { + SignedHexDisplay { + value: imm, + negative: imm < 0, + } +} + +pub fn u16_hex(value: u16) -> SignedHexDisplay<i16> { + SignedHexDisplay { + value: value as i16, + negative: false, + } } -pub fn signed_i16_hex(imm: i16) -> String { - let (sign, imm) = if imm == std::i16::MIN { - (false, imm) - } else if imm < 0 { - (true, -imm) - } else { - (false, imm) - }; - format!("{}{:#x}", if sign { "-" } else { "" } , imm) +pub fn signed_i16_hex(imm: i16) -> SignedHexDisplay<i16> { + SignedHexDisplay { + value: imm, + negative: imm < 0, + } } -pub fn signed_i32_hex(imm: i32) -> String { - let (sign, imm) = if imm == std::i32::MIN { - (false, imm) - } else if imm < 0 { - (true, -imm) - } else { - (false, imm) - }; - format!("{}{:#x}", if sign { "-" } else { "" } , imm) +pub fn u32_hex(value: u32) -> SignedHexDisplay<i32> { + SignedHexDisplay { + value: value as i32, + negative: false, + } } -pub fn signed_i64_hex(imm: i64) -> String { - let (sign, imm) = if imm == std::i64::MIN { - (false, imm) - } else if imm < 0 { - (true, -imm) - } else { - (false, imm) - }; - format!("{}{:#x}", if sign { "-" } else { "" } , imm) +pub fn signed_i32_hex(imm: i32) -> SignedHexDisplay<i32> { + SignedHexDisplay { + value: imm, + negative: imm < 0, + } +} + +pub fn u64_hex(value: u64) -> SignedHexDisplay<i64> { + SignedHexDisplay { + value: value as i64, + negative: false, + } +} + +pub fn signed_i64_hex(imm: i64) -> SignedHexDisplay<i64> { + SignedHexDisplay { + value: imm, + negative: imm < 0, + } } @@ -1,163 +1,31 @@ -extern crate num_traits; -extern crate termion; -#[cfg(feature="use-serde")] -extern crate serde; - -use std::str::FromStr; -use std::hash::Hash; +#![no_std] -use std::fmt::{Debug, Display, Formatter}; +#[cfg(feature = "std")] +#[macro_use] +extern crate std; -use std::ops::{Add, Sub, AddAssign, SubAssign}; - -use num_traits::identities; -use num_traits::{Bounded, WrappingAdd, WrappingSub, CheckedAdd, CheckedSub}; - -use termion::color; +use core::fmt::{self, Debug, Display}; +use core::hash::Hash; +extern crate num_traits; #[cfg(feature="use-serde")] -use serde::{Serialize, Deserialize}; - -pub mod display; - // This is pretty wonk.. -pub trait AddressDisplay { - fn stringy(&self) -> String; -} - -/* - * TODO: this should be FromStr. - * that would require newtyping address primitives, though - * - * this is not out of the question, BUT is way more work than - * i want to put in right now - * - * this is one of those "clean it up later" situations - */ -pub trait AddrParse: Sized { - type Err; - fn parse_from(s: &str) -> Result<Self, Self::Err>; -} +extern crate serde; +#[cfg(feature="colors")] +extern crate termion; #[cfg(feature="use-serde")] -pub trait Address where Self: - Serialize + for<'de> Deserialize<'de> + - Debug + Display + AddressDisplay + - Copy + Clone + Sized + Hash + - Ord + Eq + PartialEq + Bounded + - Add<Output=Self> + Sub<Output=Self> + - AddAssign + SubAssign + - WrappingAdd + WrappingSub + - CheckedAdd + CheckedSub + - AddrParse + - Hash + - identities::One + identities::Zero { - fn to_linear(&self) -> usize; - -} -#[cfg(not(feature="use-serde"))] -pub trait Address where Self: - Debug + Display + AddressDisplay + - Copy + Clone + Sized + Hash + - Ord + Eq + PartialEq + Bounded + - Add<Output=Self> + Sub<Output=Self> + - AddAssign + SubAssign + - WrappingAdd + WrappingSub + - CheckedAdd + CheckedSub + - AddrParse + - Hash + - identities::One + identities::Zero { - fn to_linear(&self) -> usize; - -} -/* -impl <T> Address for T where T: Sized + Ord + Add<Output=Self> + From<u16> + Into<usize> { - fn to_linear(&self) -> usize { *self.into() } -} -*/ - -impl AddrParse for usize { - type Err = std::num::ParseIntError; - fn parse_from(s: &str) -> Result<Self, Self::Err> { - if s.starts_with("0x") { - usize::from_str_radix(&s[2..], 16) - } else { - usize::from_str(s) - } - } -} - -impl AddressDisplay for usize { - fn stringy(&self) -> String { - format!("{:#x}", self) - } -} - -impl AddrParse for u64 { - type Err = std::num::ParseIntError; - fn parse_from(s: &str) -> Result<Self, Self::Err> { - if s.starts_with("0x") { - u64::from_str_radix(&s[2..], 16) - } else { - u64::from_str(s) - } - } -} - -impl AddressDisplay for u64 { - fn stringy(&self) -> String { - format!("{:#x}", self) - } -} - -impl AddrParse for u32 { - type Err = std::num::ParseIntError; - fn parse_from(s: &str) -> Result<Self, Self::Err> { - if s.starts_with("0x") { - u32::from_str_radix(&s[2..], 16) - } else { - u32::from_str(s) - } - } -} - -impl AddressDisplay for u32 { - fn stringy(&self) -> String { - format!("{:#x}", self) - } -} - -impl AddrParse for u16 { - type Err = std::num::ParseIntError; - fn parse_from(s: &str) -> Result<Self, Self::Err> { - if s.starts_with("0x") { - u16::from_str_radix(&s[2..], 16) - } else { - u16::from_str(s) - } - } -} - -impl AddressDisplay for u16 { - fn stringy(&self) -> String { - format!("{:#x}", self) - } -} +use serde::{Serialize, Deserialize}; -impl Address for u16 { - fn to_linear(&self) -> usize { *self as usize } -} +mod address; +pub use address::{Address, AddressBase}; -impl Address for u32 { - fn to_linear(&self) -> usize { *self as usize } -} +mod color; +pub use color::{Colorize, NoColors, YaxColors}; -impl Address for u64 { - fn to_linear(&self) -> usize { *self as usize } -} +#[cfg(feature="colors")] +pub use color::ColorSettings; -impl Address for usize { - fn to_linear(&self) -> usize { *self } -} +pub mod display; pub trait DecodeError { fn data_exhausted(&self) -> bool; @@ -204,335 +72,13 @@ pub trait Instruction { fn well_defined(&self) -> bool; } -#[cfg(feature="use-serde")] -impl Serialize for ColorSettings { - fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - use serde::ser::SerializeStruct; - let s = serializer.serialize_struct("ColorSettings", 0)?; - s.end() - } -} - -#[allow(dead_code)] -pub struct ColorSettings { - arithmetic: color::Fg<&'static dyn color::Color>, - stack: color::Fg<&'static dyn color::Color>, - nop: color::Fg<&'static dyn color::Color>, - stop: color::Fg<&'static dyn color::Color>, - control: color::Fg<&'static dyn color::Color>, - data: color::Fg<&'static dyn color::Color>, - comparison: color::Fg<&'static dyn color::Color>, - invalid: color::Fg<&'static dyn color::Color>, - platform: color::Fg<&'static dyn color::Color>, - misc: color::Fg<&'static dyn color::Color>, - - register: color::Fg<&'static dyn color::Color>, - program_counter: color::Fg<&'static dyn color::Color>, - - number: color::Fg<&'static dyn color::Color>, - zero: color::Fg<&'static dyn color::Color>, - one: color::Fg<&'static dyn color::Color>, - minus_one: color::Fg<&'static dyn color::Color>, - - function: color::Fg<&'static dyn color::Color>, - symbol: color::Fg<&'static dyn color::Color>, - address: color::Fg<&'static dyn color::Color> -} - -impl Default for ColorSettings { - fn default() -> ColorSettings { - ColorSettings { - /* - arithmetic: color::Fg(&color::LightYellow), - stack: color::Fg(&color::Magenta), - nop: color::Fg(&color::Blue), - stop: color::Fg(&color::LightRed), - control: color::Fg(&color::Green), - data: color::Fg(&color::LightMagenta), - comparison: color::Fg(&color::Yellow), - invalid: color::Fg(&color::Red), - platform: color::Fg(&color::Cyan), - misc: color::Fg(&color::LightCyan), - */ - arithmetic: color::Fg(&color::Yellow), - stack: color::Fg(&color::Magenta), - nop: color::Fg(&color::Blue), - stop: color::Fg(&color::Red), - control: color::Fg(&color::Red), - data: color::Fg(&color::Yellow), - comparison: color::Fg(&color::Yellow), - invalid: color::Fg(&color::Red), - platform: color::Fg(&color::LightBlue), - misc: color::Fg(&color::LightCyan), - - register: color::Fg(&color::Cyan), - program_counter: color::Fg(&color::Red), - - number: color::Fg(&color::White), - zero: color::Fg(&color::White), - one: color::Fg(&color::White), - minus_one: color::Fg(&color::White), - - function: color::Fg(&color::LightGreen), - symbol: color::Fg(&color::LightGreen), - address: color::Fg(&color::Green) - } - } -} - -pub trait YaxColors { - fn arithmetic_op<T: Display>(&self, t: T) -> Colored<T>; - fn stack_op<T: Display>(&self, t: T) -> Colored<T>; - fn nop_op<T: Display>(&self, t: T) -> Colored<T>; - fn stop_op<T: Display>(&self, t: T) -> Colored<T>; - fn control_flow_op<T: Display>(&self, t: T) -> Colored<T>; - fn data_op<T: Display>(&self, t: T) -> Colored<T>; - fn comparison_op<T: Display>(&self, t: T) -> Colored<T>; - fn invalid_op<T: Display>(&self, t: T) -> Colored<T>; - fn platform_op<T: Display>(&self, t: T) -> Colored<T>; - fn misc_op<T: Display>(&self, t: T) -> Colored<T>; - - fn register<T: Display>(&self, t: T) -> Colored<T>; - fn program_counter<T: Display>(&self, t: T) -> Colored<T>; - fn number<T: Display>(&self, t: T) -> Colored<T>; - fn zero<T: Display>(&self, t: T) -> Colored<T>; - fn one<T: Display>(&self, t: T) -> Colored<T>; - fn minus_one<T: Display>(&self, t: T) -> Colored<T>; - fn address<T: Display>(&self, t: T) -> Colored<T>; - fn symbol<T: Display>(&self, t: T) -> Colored<T>; - fn function<T: Display>(&self, t: T) -> Colored<T>; -} - -impl YaxColors for ColorSettings { - fn arithmetic_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.arithmetic) - } - fn stack_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.stack) - } - fn nop_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.nop) - } - fn stop_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.stop) - } - fn control_flow_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.control) - } - fn data_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.data) - } - fn comparison_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.comparison) - } - fn invalid_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.invalid) - } - fn misc_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.misc) - } - fn platform_op<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.platform) - } - - fn register<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.register) - } - fn program_counter<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.program_counter) - } - fn number<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.number) - } - fn zero<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.zero) - } - fn one<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.one) - } - fn minus_one<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.minus_one) - } - fn address<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.address) - } - fn symbol<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.symbol) - } - fn function<T: Display>(&self, t: T) -> Colored<T> { - Colored::Color(t, self.function) - } -} - -impl <'a> YaxColors for Option<&'a ColorSettings> { - fn arithmetic_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.arithmetic_op(t) } - None => { Colored::Just(t) } - } - } - fn stack_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.stack_op(t) } - None => { Colored::Just(t) } - } - } - fn nop_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.nop_op(t) } - None => { Colored::Just(t) } - } - } - fn stop_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.stop_op(t) } - None => { Colored::Just(t) } - } - } - fn control_flow_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.control_flow_op(t) } - None => { Colored::Just(t) } - } - } - fn data_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.data_op(t) } - None => { Colored::Just(t) } - } - } - fn comparison_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.comparison_op(t) } - None => { Colored::Just(t) } - } - } - fn invalid_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.invalid_op(t) } - None => { Colored::Just(t) } - } - } - fn misc_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.misc_op(t) } - None => { Colored::Just(t) } - } - } - fn platform_op<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.platform_op(t) } - None => { Colored::Just(t) } - } - } - - fn register<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.register(t) } - None => { Colored::Just(t) } - } - } - fn program_counter<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.program_counter(t) } - None => { Colored::Just(t) } - } - } - fn number<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.number(t) } - None => { Colored::Just(t) } - } - } - fn zero<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.zero(t) } - None => { Colored::Just(t) } - } - } - fn one<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.one(t) } - None => { Colored::Just(t) } - } - } - fn minus_one<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.minus_one(t) } - None => { Colored::Just(t) } - } - } - fn address<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.address(t) } - None => { Colored::Just(t) } - } - } - fn symbol<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.symbol(t) } - None => { Colored::Just(t) } - } - } - fn function<T: Display>(&self, t: T) -> Colored<T> { - match self { - Some(colors) => { colors.function(t) } - None => { Colored::Just(t) } - } - } -} - -pub enum Colored<T: Display> { - Color(T, color::Fg<&'static dyn color::Color>), - Just(T) -} - -impl <T: Display> Display for Colored<T> { - fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result { - match self { - Colored::Color(t, color) => { - write!(fmt, "{}{}{}", color, t, color::Fg(color::Reset)) - }, - Colored::Just(t) => { - write!(fmt, "{}", t) - } - } - } -} - -/* - * can this be a derivable trait or something? - */ -/* -impl <T: Colorize> Display for T { - fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result { - self.colorize(None, fmt) - } -} -*/ - -pub trait Colorize<T: std::fmt::Write> { - fn colorize(&self, colors: Option<&ColorSettings>, out: &mut T) -> std::fmt::Result; -} - -/* - * and make this auto-derive from a ShowContextual impl? - */ -/* -impl <T, U> Colorize for T where T: ShowContextual<Ctx=U> { - fn colorize(&self, colors: Option<&ColorSettings>, fmt: &mut Formatter) -> std::fmt::Result { - self.contextualize(colors, None, fmt) - } -} -*/ - -pub trait ShowContextual<Addr, Ctx: ?Sized, T: std::fmt::Write> { - fn contextualize(&self, colors: Option<&ColorSettings>, address: Addr, context: Option<&Ctx>, out: &mut T) -> std::fmt::Result; +pub trait ShowContextual<Addr, Ctx: ?Sized, Color: Display, T: fmt::Write, Y: YaxColors<Color>> { + fn contextualize(&self, colors: &Y, address: Addr, context: Option<&Ctx>, out: &mut T) -> fmt::Result; } /* -impl <C: ?Sized, T: std::fmt::Write, U: Colorize<T>> ShowContextual<C, T> for U { - fn contextualize(&self, colors: Option<&ColorSettings>, context: Option<&C>, out: &mut T) -> std::fmt::Result { +impl <C: ?Sized, T: fmt::Write, U: Colorize<T>> ShowContextual<C, T> for U { + fn contextualize(&self, colors: Option<&ColorSettings>, context: Option<&C>, out: &mut T) -> fmt::Result { self.colorize(colors, out) } } |