Skip to content

Commit

Permalink
Merge #323
Browse files Browse the repository at this point in the history
323: Merge I128/Ixx and U128/Uxx variants r=japaric a=Sh3Rm4n

Closes #314 

Also lift 32 bit range for bitfields introduced in #13
Could be split into another PR, if concerns are raised.

Co-authored-by: Fabian Viöl <f.vioel@googlemail.com>
  • Loading branch information
bors[bot] and Sh3Rm4n authored Jan 4, 2021
2 parents c4461eb + a270f5c commit 666a205
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 51 deletions.
114 changes: 76 additions & 38 deletions decoder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,9 @@ enum Arg<'t> {
Bool(Arc<Bool>),
F32(f32),
/// U8, U16, U24 and U32
Uxx(u64),
U128(u128),
Uxx(u128),
/// I8, I16, I24 and I32
Ixx(i64),
I128(i128),
Ixx(i128),
/// Str
Str(String),
/// Interned string
Expand Down Expand Up @@ -697,7 +695,7 @@ impl<'t, 'b> Decoder<'t, 'b> {
match &param.ty {
Type::U8 => {
let data = self.bytes.read_u8()?;
args.push(Arg::Uxx(data as u64));
args.push(Arg::Uxx(data as u128));
}

Type::Bool => {
Expand Down Expand Up @@ -739,78 +737,84 @@ impl<'t, 'b> Decoder<'t, 'b> {
}
Type::I16 => {
let data = self.bytes.read_i16::<LE>()?;
args.push(Arg::Ixx(data as i64));
args.push(Arg::Ixx(data as i128));
}
Type::I32 => {
let data = self.bytes.read_i32::<LE>()?;
args.push(Arg::Ixx(data as i64));
args.push(Arg::Ixx(data as i128));
}
Type::I64 => {
let data = self.bytes.read_i64::<LE>()?;
args.push(Arg::Ixx(data as i64));
args.push(Arg::Ixx(data as i128));
}
Type::I128 => {
let data = self.bytes.read_i128::<LE>()?;
args.push(Arg::I128(data));
args.push(Arg::Ixx(data));
}
Type::I8 => {
let data = self.bytes.read_i8()?;
args.push(Arg::Ixx(data as i64));
args.push(Arg::Ixx(data as i128));
}
Type::Isize => {
// Signed isize is encoded in zigzag-encoding.
let unsigned = read_leb128(&mut self.bytes)?;
args.push(Arg::Ixx(zigzag_decode(unsigned)))
args.push(Arg::Ixx(zigzag_decode(unsigned) as i128))
}
Type::U16 => {
let data = self.bytes.read_u16::<LE>()?;
args.push(Arg::Uxx(data as u64));
args.push(Arg::Uxx(data as u128));
}
Type::U24 => {
let data_low = self.bytes.read_u8()?;
let data_high = self.bytes.read_u16::<LE>()?;
let data = data_low as u64 | (data_high as u64) << 8;
args.push(Arg::Uxx(data as u64));
let data = data_low as u128 | (data_high as u128) << 8;
args.push(Arg::Uxx(data as u128));
}
Type::U32 => {
let data = self.bytes.read_u32::<LE>()?;
args.push(Arg::Uxx(data as u64));
args.push(Arg::Uxx(data as u128));
}
Type::U64 => {
let data = self.bytes.read_u64::<LE>()?;
args.push(Arg::Uxx(data as u64));
args.push(Arg::Uxx(data as u128));
}
Type::U128 => {
let data = self.bytes.read_u128::<LE>()?;
args.push(Arg::U128(data));
args.push(Arg::Uxx(data as u128));
}
Type::Usize => {
let unsigned = read_leb128(&mut self.bytes)?;
args.push(Arg::Uxx(unsigned))
args.push(Arg::Uxx(unsigned as u128))
}
Type::F32 => {
let data = self.bytes.read_u32::<LE>()?;
args.push(Arg::F32(f32::from_bits(data)));
}
Type::BitField(range) => {
let mut data: u64;
let mut data: u128;
let lowest_byte = range.start / 8;
// -1 because `range` is range-exclusive
let highest_byte = (range.end - 1) / 8;
let size_after_truncation = highest_byte - lowest_byte + 1; // in octets

match size_after_truncation {
1 => {
data = self.bytes.read_u8()? as u64;
data = self.bytes.read_u8()? as u128;
}
2 => {
data = self.bytes.read_u16::<LE>()? as u64;
data = self.bytes.read_u16::<LE>()? as u128;
}
3 => {
data = self.bytes.read_u24::<LE>()? as u64;
data = self.bytes.read_u24::<LE>()? as u128;
}
4 => {
data = self.bytes.read_u32::<LE>()? as u64;
data = self.bytes.read_u32::<LE>()? as u128;
}
5..=8 => {
data = self.bytes.read_u64::<LE>()? as u128;
}
9..=16 => {
data = self.bytes.read_u128::<LE>()? as u128;
}
_ => {
unreachable!();
Expand Down Expand Up @@ -1009,18 +1013,27 @@ fn format_args_real(
Arg::Uxx(x) => {
match param.ty {
Type::BitField(range) => {
let left_zeroes = mem::size_of::<u64>() * 8 - range.end as usize;
let left_zeroes = mem::size_of::<u128>() * 8 - range.end as usize;
let right_zeroes = left_zeroes + range.start as usize;
// isolate the desired bitfields
let bitfields = (*x << left_zeroes) >> right_zeroes;
format_u128(bitfields as u128, hint, &mut buf)?;

if let Some(DisplayHint::Ascii) = hint {
let bstr = bitfields
.to_be_bytes()
.iter()
.skip(right_zeroes / 8)
.copied()
.collect::<Vec<u8>>();
format_bytes(&bstr, hint, &mut buf)?
} else {
format_u128(bitfields as u128, hint, &mut buf)?;
}
}
_ => format_u128(*x as u128, hint, &mut buf)?,
}
}
Arg::U128(x) => format_u128(*x, hint, &mut buf)?,
Arg::Ixx(x) => format_i128(*x as i128, hint, &mut buf)?,
Arg::I128(x) => format_i128(*x, hint, &mut buf)?,
Arg::Str(x) => format_str(x, hint, &mut buf)?,
Arg::IStr(x) => format_str(x, hint, &mut buf)?,
Arg::Format { format, args } => buf.push_str(&format_args(format, args, hint)),
Expand Down Expand Up @@ -1167,17 +1180,17 @@ mod tests {
format: FMT,
timestamp: 2,
args: vec![
Arg::Uxx(42), // u8
Arg::Uxx(u16::max_value().into()), // u16
Arg::Uxx(0x10000), // u24
Arg::Uxx(u32::max_value().into()), // u32
Arg::Uxx(u64::max_value().into()), // u64
Arg::U128(u128::max_value().into()),
Arg::Ixx(-1), // i8
Arg::Ixx(-1), // i16
Arg::Ixx(-1), // i32
Arg::Ixx(-1), // i64
Arg::I128(-1), // i128
Arg::Uxx(42), // u8
Arg::Uxx(u16::max_value().into()), // u16
Arg::Uxx(0x10000), // u24
Arg::Uxx(u32::max_value().into()), // u32
Arg::Uxx(u64::max_value().into()), // u64
Arg::Uxx(u128::max_value().into()), // u128
Arg::Ixx(-1), // i8
Arg::Ixx(-1), // i16
Arg::Ixx(-1), // i32
Arg::Ixx(-1), // i64
Arg::Ixx(-1), // i128
],
},
bytes.len(),
Expand Down Expand Up @@ -1608,6 +1621,31 @@ mod tests {
);
}

#[test]
fn bitfields_u128() {
let bytes = [
0, // index
2, // timestamp
0b1110_0101, // 120..127
0b1110_0101, // 112..119
0b0000_0000, // 104..111
0b0000_0000, // 96..103
0b0000_0000, // 88..95
0b0000_0000, // 80..87
0b0000_0000, // 72..79
0b0000_0000, // 64..71
0b0000_0000, // 56..63
0b0000_0000, // 48..55
0b0000_0000, // 40..47
0b0000_0000, // 32..39
0b0000_0000, // 24..31
0b0000_0000, // 16..23
0b0000_0000, // 8..15
0b0000_0000, // 0..7
];
decode_and_expect("x: {0=119..124:b}", &bytes, "0.000002 INFO x: 0b1011");
}

#[test]
fn slice() {
let bytes = [
Expand Down
2 changes: 1 addition & 1 deletion firmware/qemu/src/bin/hints.out
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@
0.000039 INFO hex 0xa
0.000040 INFO HEX 0xA
0.000041 INFO binary 0b1010
0.000042 INFO ASCII 10
0.000042 INFO ASCII b"\n"
0.000043 INFO Debug 10
2 changes: 1 addition & 1 deletion firmware/qemu/src/bin/hints.release.out
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@
0.000039 INFO hex 0xa
0.000040 INFO HEX 0xA
0.000041 INFO binary 0b1010
0.000042 INFO ASCII 10
0.000042 INFO ASCII b"\n"
0.000043 INFO Debug 10
3 changes: 2 additions & 1 deletion firmware/qemu/src/bin/log.out
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,5 @@
0.000103 INFO EnumLarge::A051
0.000104 INFO EnumLarge::A269
0.000105 INFO S { x: "hi" }
0.000106 INFO QEMU test finished!
0.000106 INFO bitfields 0x97 0b10000100 12 b"42" b"hello"
0.000107 INFO QEMU test finished!
3 changes: 2 additions & 1 deletion firmware/qemu/src/bin/log.release.out
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,5 @@
0.000101 INFO EnumLarge::A051
0.000102 INFO EnumLarge::A269
0.000103 INFO S { x: "hi" }
0.000104 INFO QEMU test finished!
0.000104 INFO bitfields 0x97 0b10000100 12 b"42" b"hello"
0.000105 INFO QEMU test finished!
11 changes: 10 additions & 1 deletion firmware/qemu/src/bin/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ fn main() -> ! {
);
defmt::info!("usize: 0 = {=usize}, MAX = {=usize}", 0, usize::max_value());
defmt::info!("bitfields {0=0..3} {0=5..7}", 0b0110_0011_1101_0110u16);

defmt::trace!("log trace");
defmt::debug!("log debug");
defmt::info!("log info");
Expand Down Expand Up @@ -539,6 +538,16 @@ fn main() -> ! {
defmt::info!("{:?}", S { x: "hi" });
}

defmt::info!(
"bitfields \
{0=120..128:x} \
{0=112..120:b} \
{0=80..88} \
{0=48..64:a} \
{=8..48:a}",
0x9784_89AE_FF0C_5900_3432_6865_6C6C_6F00u128
);

defmt::info!("QEMU test finished!");

loop {
Expand Down
7 changes: 7 additions & 0 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,13 @@ impl Codegen {
4 => {
exprs.push(quote!(_fmt_.u32(&defmt::export::truncate((*#arg) >> (#lowest_byte * 8)))));
}
5..=8 => {
exprs.push(quote!(_fmt_.u64(&defmt::export::truncate((*#arg) >> (#lowest_byte * 8)))));
}
9..=16 => {
exprs.push(quote!(_fmt_.u128(&defmt::export::truncate((*#arg) >> (#lowest_byte * 8)))));
}

_ => unreachable!(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion macros/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<'a> Symbol<'a> {
pub fn new(tag: &'a str, data: &'a str) -> Self {
Self {
// `CARGO_PKG_NAME` is set to the invoking package's name.
package: env::var("CARGO_PKG_NAME").unwrap_or("<unknown>".to_string()),
package: env::var("CARGO_PKG_NAME").unwrap_or_else(|_| "<unknown>".to_string()),
disambiguator: {
// We want a deterministic, but unique-per-macro-invocation identifier. For that we
// hash the call site `Span`'s debug representation, which contains a counter that
Expand Down
16 changes: 9 additions & 7 deletions parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fn parse_range(mut s: &str) -> Option<(Range<u8>, usize /* consumed */)> {
return None;
}

if start >= 32 || end >= 32 {
if start >= 128 || end > 128 {
return None;
}

Expand Down Expand Up @@ -169,7 +169,7 @@ fn parse_param(mut input: &str, mode: ParserMode) -> Result<Param, Cow<'static,

// First, optional argument index.
let mut index = None;
let index_end = input.find(|c: char| !c.is_digit(10)).unwrap_or(input.len());
let index_end = input.find(|c: char| !c.is_digit(10)).unwrap_or_else(|| input.len());

if index_end != 0 {
index = Some(
Expand All @@ -188,7 +188,7 @@ fn parse_param(mut input: &str, mode: ParserMode) -> Result<Param, Cow<'static,
input = &input[TYPE_PREFIX.len()..];

// type is delimited by `HINT_PREFIX` or end-of-string
let type_end = input.find(HINT_PREFIX).unwrap_or(input.len());
let type_end = input.find(HINT_PREFIX).unwrap_or_else(|| input.len());
let type_fragment = &input[..type_end];

static FORMAT_ARRAY_START: &str = "[?;";
Expand Down Expand Up @@ -886,10 +886,12 @@ mod tests {
assert!(parse("{=0..0}", ParserMode::Strict).is_err());
// start > end
assert!(parse("{=1..0}", ParserMode::Strict).is_err());
// out of 32-bit range
assert!(parse("{=0..32}", ParserMode::Strict).is_err());
// just inside 32-bit range
assert!(parse("{=0..31}", ParserMode::Strict).is_ok());
// out of 128-bit range
assert!(parse("{=0..129}", ParserMode::Strict).is_err());
assert!(parse("{=128..128}", ParserMode::Strict).is_err());
// just inside 128-bit range
assert!(parse("{=0..128}", ParserMode::Strict).is_ok());
assert!(parse("{=127..128}", ParserMode::Strict).is_ok());

// missing parts
assert!(parse("{=0..4", ParserMode::Strict).is_err());
Expand Down
31 changes: 31 additions & 0 deletions src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ mod sealed {
}
}

impl Truncate<u8> for u128 {
fn truncate(self) -> u8 {
self as u8
}
}

// needed so we can call truncate() without having to check whether truncation is necessary first
impl Truncate<u16> for u16 {
fn truncate(self) -> u16 {
Expand All @@ -123,6 +129,12 @@ mod sealed {
}
}

impl Truncate<u16> for u128 {
fn truncate(self) -> u16 {
self as u16
}
}

// needed so we can call truncate() without having to check whether truncation is necessary first
impl Truncate<u32> for u32 {
fn truncate(self) -> u32 {
Expand All @@ -136,13 +148,32 @@ mod sealed {
}
}

impl Truncate<u32> for u128 {
fn truncate(self) -> u32 {
self as u32
}
}

// needed so we can call truncate() without having to check whether truncation is necessary first
impl Truncate<u64> for u64 {
fn truncate(self) -> u64 {
self
}
}

impl Truncate<u64> for u128 {
fn truncate(self) -> u64 {
self as u64
}
}

// needed so we can call truncate() without having to check whether truncation is necessary first
impl Truncate<u128> for u128 {
fn truncate(self) -> u128 {
self
}
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct NoneError;

Expand Down

0 comments on commit 666a205

Please sign in to comment.