Skip to content

Commit ceefaaa

Browse files
committed
🐛 Fix negative int checks
1 parent ff0107b commit ceefaaa

File tree

4 files changed

+73
-13
lines changed

4 files changed

+73
-13
lines changed

Cargo.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bitfield-struct"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
edition = "2021"
55
authors = ["Lars Wrenger <lars@wrenger.net>"]
66
description = "Procedural macro for bitfields."

src/lib.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ impl ToTokens for Member {
442442
}
443443
};
444444

445-
let mask: u128 = !0 >> (u128::BITS as usize - bits);
445+
let bits = *bits as u32;
446+
let mask: u128 = !0 >> (u128::BITS - bits);
446447
let mask = syn::LitInt::new(&format!("0x{mask:x}"), Span::mixed_site());
447448

448449
let code = match class {
@@ -466,13 +467,14 @@ impl ToTokens for Member {
466467
#doc
467468
#[doc = #location]
468469
#vis const fn #with_ident(self, value: #ty) -> Self {
469-
debug_assert!(value <= #mask);
470+
#[allow(unused_comparisons)]
471+
debug_assert!(if value >= 0 { value & !#mask == 0 } else { !value & !#mask == 0 }, "value out of bounds");
470472
Self(self.0 & !(#mask << #offset) | (value as #base_ty & #mask) << #offset)
471473
}
472474
#doc
473475
#[doc = #location]
474476
#vis const fn #ident(&self) -> #ty {
475-
let shift = #ty::BITS as usize - #bits;
477+
let shift = #ty::BITS - #bits;
476478
(((self.0 >> #offset) as #ty) << shift) >> shift
477479
}
478480
},
@@ -483,13 +485,14 @@ impl ToTokens for Member {
483485
#[doc = #location]
484486
#vis fn #with_ident(self, value: #ty) -> Self {
485487
let value: #base_ty = value.into();
486-
debug_assert!(value <= #mask);
488+
#[allow(unused_comparisons)]
489+
debug_assert!(if value >= 0 { value & !#mask == 0 } else { !value & !#mask == 0 }, "value out of bounds");
487490
Self(self.0 & !(#mask << #offset) | (value & #mask) << #offset)
488491
}
489492
#doc
490493
#[doc = #location]
491494
#vis fn #ident(&self) -> #ty {
492-
let shift = #base_ty::BITS as usize - #bits;
495+
let shift = #base_ty::BITS - #bits;
493496
(((self.0 >> #offset) << shift) >> shift).into()
494497
}
495498
},

tests/test.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,60 @@ fn debug() {
119119
let full = Full::new().with_data(123);
120120
println!("{full:?}");
121121
}
122+
123+
#[test]
124+
fn positive() {
125+
#[bitfield(u32)]
126+
struct MyBitfield {
127+
#[bits(3)]
128+
positive: u32,
129+
#[bits(29)]
130+
_p: (),
131+
}
132+
133+
let v = MyBitfield::new().with_positive(0);
134+
assert_eq!(v.positive(), 0);
135+
let v = MyBitfield::new().with_positive(1);
136+
assert_eq!(v.positive(), 1);
137+
let v = MyBitfield::new().with_positive(7);
138+
assert_eq!(v.positive(), 7);
139+
}
140+
141+
#[test]
142+
fn negative() {
143+
#[bitfield(u32)]
144+
struct MyBitfield {
145+
#[bits(3)]
146+
negative: i32,
147+
#[bits(29)]
148+
_p: (),
149+
}
150+
151+
let v = MyBitfield::new().with_negative(-3);
152+
assert_eq!(v.negative(), -3);
153+
let v = MyBitfield::new().with_negative(0);
154+
assert_eq!(v.negative(), 0);
155+
let v = MyBitfield::new().with_negative(3);
156+
assert_eq!(v.negative(), 3);
157+
let v = MyBitfield::new().with_negative(-4);
158+
assert_eq!(v.negative(), -4);
159+
}
160+
161+
#[test]
162+
fn entirely_negative() {
163+
#[bitfield(u32)]
164+
struct MyBitfield {
165+
negative: i32,
166+
}
167+
168+
let v = MyBitfield::new().with_negative(-3);
169+
assert_eq!(v.negative(), -3);
170+
let v = MyBitfield::new().with_negative(0);
171+
assert_eq!(v.negative(), 0);
172+
let v = MyBitfield::new().with_negative(3);
173+
assert_eq!(v.negative(), 3);
174+
let v = MyBitfield::new().with_negative(i32::MIN);
175+
assert_eq!(v.negative(), i32::MIN);
176+
let v = MyBitfield::new().with_negative(i32::MAX);
177+
assert_eq!(v.negative(), i32::MAX);
178+
}

0 commit comments

Comments
 (0)