Skip to content

Commit a85e77d

Browse files
committed
Add missing API for BV
1 parent 4f9fcfe commit a85e77d

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

z3/src/ast.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,34 @@ impl<'ctx> BV<'ctx> {
13461346
Some(unsafe { Self::wrap(ctx, ast) })
13471347
}
13481348

1349+
pub fn from_bit_vec(ctx: &'ctx Context, bit_vec: Vec<bool>) -> Option<BV<'ctx>> {
1350+
let ast = unsafe {
1351+
let size = bit_vec.len() as u32;
1352+
let bits = bit_vec.as_ptr();
1353+
1354+
let numeral_ptr = Z3_mk_bv_numeral(ctx.z3_ctx, size, bits);
1355+
if numeral_ptr.is_null() {
1356+
return None;
1357+
}
1358+
1359+
numeral_ptr
1360+
};
1361+
Some(unsafe { Self::wrap(ctx, ast) })
1362+
}
1363+
1364+
pub fn from_byte_vec(ctx: &'ctx Context, byte_vec: Vec<u8>) -> Option<BV<'ctx>> {
1365+
let mut bit_vec = Vec::with_capacity(byte_vec.len() * 8);
1366+
for item in byte_vec {
1367+
for offset in 0..8 {
1368+
let mask = 1 << offset;
1369+
let bit = item & mask != 0;
1370+
bit_vec.push(bit);
1371+
}
1372+
}
1373+
1374+
Self::from_bit_vec(ctx, bit_vec)
1375+
}
1376+
13491377
pub fn new_const<S: Into<Symbol>>(ctx: &'ctx Context, name: S, sz: u32) -> BV<'ctx> {
13501378
let sort = Sort::bitvector(ctx, sz);
13511379
unsafe {

z3/tests/lib.rs

+43
Original file line numberDiff line numberDiff line change
@@ -2002,3 +2002,46 @@ fn test_model_iter() {
20022002
vec![ast::Dynamic::new_const(&ctx, "a", &Sort::int(&ctx))]
20032003
);
20042004
}
2005+
2006+
#[test]
2007+
fn test_bitvector_from_bit_vec() {
2008+
let cfg = Config::new();
2009+
let ctx = Context::new(&cfg);
2010+
2011+
// 0b01010101
2012+
let bit_vec = vec![true, false, true, false, true, false, true, false];
2013+
2014+
let a = ast::BV::new_const(&ctx, "a", 8);
2015+
let b = ast::BV::from_bit_vec(&ctx, bit_vec).unwrap();
2016+
2017+
let solver = Solver::new(&ctx);
2018+
solver.assert(&a._eq(&b));
2019+
assert_eq!(solver.check(), SatResult::Sat);
2020+
2021+
let model = solver.get_model().unwrap();
2022+
let av = model.eval(&a, true).unwrap().to_string();
2023+
assert_eq!(av, "#x55".to_string());
2024+
}
2025+
2026+
#[test]
2027+
fn test_bitvector_from_byte_vec() {
2028+
let cfg = Config::new();
2029+
let ctx = Context::new(&cfg);
2030+
2031+
// 0x55AA
2032+
// 85 = 0x55 = 01010101
2033+
// 170 = 0xAA = 10101010
2034+
// The array should be ordered like this (at least that is how it works in rust internally)
2035+
let byte_vec = vec![170, 85];
2036+
2037+
let a = ast::BV::new_const(&ctx, "a", 16);
2038+
let b = ast::BV::from_byte_vec(&ctx, byte_vec).unwrap();
2039+
2040+
let solver = Solver::new(&ctx);
2041+
solver.assert(&a._eq(&b));
2042+
assert_eq!(solver.check(), SatResult::Sat);
2043+
2044+
let model = solver.get_model().unwrap();
2045+
let av = model.eval(&a, true).unwrap().to_string();
2046+
assert_eq!(av, "#x55aa".to_string());
2047+
}

0 commit comments

Comments
 (0)