crucible/sym_bytes.rs
1use core::ops::{Deref, DerefMut};
2use crate::crucible_assume;
3use crate::array::Array;
4use crate::symbolic::Symbolic;
5
6/// An array of symbolic bytes, backed by an SMT array. In some cases, `crux-mir` can analyze
7/// tests using `SymBytes` more efficiently than tests that use `Vec<u8>`. Otherwise, `SymBytes`
8/// and `Vec<u8>` are mostly equivalent.
9pub struct SymBytes {
10 arr: Array<u8>,
11 len: usize,
12}
13
14impl SymBytes {
15 /// Create a new byte array, filling slots `0 .. len` with zeros.
16 pub fn zeroed(len: usize) -> SymBytes {
17 SymBytes {
18 arr: Array::zeroed(),
19 len,
20 }
21 }
22
23 /// Create a new byte array, filling slots `0 .. len` with symbolic values.
24 ///
25 /// This is like the trait method `Symbolic::symbolic`, but takes an additional `len` argument.
26 pub fn symbolic(desc: &str, len: usize) -> SymBytes {
27 SymBytes {
28 arr: Array::symbolic(desc),
29 len,
30 }
31 }
32
33 /// Create a new byte array, filling slots `0 .. len` with symbolic values, and constraining
34 /// the result with `f`.
35 ///
36 /// This is like the trait method `Symbolic::symbolic`, but takes an additional `len` argument.
37 pub fn symbolic_where<F>(desc: &str, len: usize, f: F) -> SymBytes
38 where F: FnOnce(&Self) -> bool {
39 let s = Self::symbolic(desc, len);
40 crucible_assume!(f(&s));
41 s
42 }
43
44 pub fn len(&self) -> usize {
45 self.len
46 }
47}
48
49impl Deref for SymBytes {
50 type Target = [u8];
51 fn deref(&self) -> &[u8] {
52 self.arr.as_slice(0, self.len)
53 }
54}
55
56impl DerefMut for SymBytes {
57 fn deref_mut(&mut self) -> &mut [u8] {
58 self.arr.as_mut_slice(0, self.len)
59 }
60}