Skip to content

Commit af11785

Browse files
author
Pascal Hertleif
authored
Merge pull request #15 from marcelbuesing/arbitrary
Generate inital arbitrary implementation
2 parents e01fe59 + 2a2d22a commit af11785

File tree

4 files changed

+96
-1
lines changed

4 files changed

+96
-1
lines changed

Cargo.lock

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

src/main.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ fn main() -> Result<()> {
6060
writeln!(&mut w, "//! - Version: `{:?}`", dbc.version())?;
6161
writeln!(&mut w)?;
6262
writeln!(&mut w, "use bitsh::Pack;")?;
63+
writeln!(w, r##"#[cfg(feature = "arb")]"##)?;
64+
writeln!(&mut w, "use arbitrary::{{Arbitrary, Unstructured}};")?;
6365
writeln!(&mut w)?;
6466

6567
render_dbc(&mut w, &dbc).context("could not generate Rust code")?;
@@ -261,6 +263,8 @@ fn render_message(mut w: impl Write, msg: &Message, dbc: &DBC) -> Result<()> {
261263
writeln!(w, "}}")?;
262264
writeln!(w)?;
263265

266+
render_arbitrary(&mut w, &msg)?;
267+
264268
let enums_for_this_message = dbc.value_descriptions().iter().filter_map(|x| {
265269
if let ValueDescription::Signal {
266270
message_id,
@@ -545,3 +549,63 @@ fn enum_variant_name(x: &str) -> String {
545549
x.to_camel_case()
546550
}
547551
}
552+
553+
fn render_arbitrary(mut w: impl Write, msg: &Message) -> Result<()> {
554+
writeln!(w, r##"#[cfg(feature = "arb")]"##)?;
555+
writeln!(
556+
w,
557+
"impl<'a> Arbitrary<'a> for {typ}",
558+
typ = type_name(msg.message_name())
559+
)?;
560+
writeln!(w, "{{")?;
561+
{
562+
let mut w = PadAdapter::wrap(&mut w);
563+
writeln!(
564+
w,
565+
"fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {{"
566+
)?;
567+
{
568+
let mut w = PadAdapter::wrap(&mut w);
569+
for signal in msg.signals() {
570+
writeln!(
571+
w,
572+
"let {field_name} = {arbitrary_value};",
573+
field_name = field_name(signal.name()),
574+
arbitrary_value = signal_to_arbitrary(signal),
575+
)?;
576+
}
577+
578+
let args: Vec<String> = msg
579+
.signals()
580+
.iter()
581+
.map(|signal| field_name(signal.name()))
582+
.collect();
583+
584+
writeln!(
585+
w,
586+
"{typ}::new({args}).map_err(|_| arbitrary::Error::IncorrectFormat)",
587+
typ = type_name(msg.message_name()),
588+
args = args.join(",")
589+
)?;
590+
}
591+
writeln!(w, "}}")?;
592+
}
593+
writeln!(w, "}}")?;
594+
595+
Ok(())
596+
}
597+
598+
fn signal_to_arbitrary(signal: &Signal) -> String {
599+
if signal.signal_size == 1 {
600+
"u.int_in_range(0..=1)? == 1".to_string()
601+
} else if signal_is_float_in_rust(signal) {
602+
// TODO generate arbitrary value for float
603+
format!("{}_f32", signal.min())
604+
} else {
605+
format!(
606+
"u.int_in_range({min}..={max})?",
607+
min = signal.min(),
608+
max = signal.max()
609+
)
610+
}
611+
}

testing/can-messages/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ authors = ["Pascal Hertleif <[email protected]>"]
55
edition = "2018"
66

77
[dependencies]
8+
arbitrary = { version = "1.0", optional = true }
89
bitsh = { git = "https://github.com/bitbleep/bitsh/" }
910

1011
[features]
11-
default = ["debug"]
12+
default = ["debug", "arb"]
13+
arb = ["arbitrary"]
1214
debug = []
1315
range_checked = []

testing/can-messages/src/messages.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
//!
77
//! - Version: `Version("43")`
88
9+
#[cfg(feature = "arb")]
10+
use arbitrary::{Arbitrary, Unstructured};
911
use bitsh::Pack;
1012

1113
/// All messages
@@ -165,6 +167,15 @@ impl core::convert::TryFrom<&[u8]> for Foo {
165167
}
166168
}
167169

170+
#[cfg(feature = "arb")]
171+
impl<'a> Arbitrary<'a> for Foo {
172+
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {
173+
let voltage = 0_f32;
174+
let current = -2048_f32;
175+
Foo::new(voltage, current).map_err(|_| arbitrary::Error::IncorrectFormat)
176+
}
177+
}
178+
168179
/// Bar
169180
///
170181
/// - ID: 512 (0x200)
@@ -424,6 +435,17 @@ impl core::convert::TryFrom<&[u8]> for Bar {
424435
}
425436
}
426437

438+
#[cfg(feature = "arb")]
439+
impl<'a> Arbitrary<'a> for Bar {
440+
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {
441+
let one = u.int_in_range(0..=3)?;
442+
let two = 0_f32;
443+
let three = u.int_in_range(0..=7)?;
444+
let four = u.int_in_range(0..=3)?;
445+
let xtype = u.int_in_range(0..=1)? == 1;
446+
Bar::new(one, two, three, four, xtype).map_err(|_| arbitrary::Error::IncorrectFormat)
447+
}
448+
}
427449
/// Defined values for Three
428450
#[derive(Clone, Copy, PartialEq)]
429451
#[cfg_attr(feature = "debug", derive(Debug))]

0 commit comments

Comments
 (0)