/src/wasm-tools/crates/wit-smith/src/lib.rs
Line | Count | Source |
1 | | //! A small crate to generate arbitrary WIT documents. |
2 | | //! |
3 | | //! This crate is modeled after the `wasm-smith` crate but is used to generate |
4 | | //! WIT documents instead of WebAssembly modules. This crate is intended to |
5 | | //! generate "interesting" WIT package structures in addition to interesting |
6 | | //! type structures. |
7 | | |
8 | | use arbitrary::{Result, Unstructured}; |
9 | | use wit_parser::{Resolve, ResolveErrorKind}; |
10 | | |
11 | | mod config; |
12 | | pub use self::config::Config; |
13 | | mod generate; |
14 | | |
15 | | /// Generates an arbitrary WIT document encoded as a WebAssembly binary. |
16 | | /// |
17 | | /// The `config` guides the generation of the document and the `u` bytes are |
18 | | /// used as input to construct the document. |
19 | 4.02k | pub fn smith(config: &Config, u: &mut Unstructured<'_>) -> Result<Vec<u8>> { |
20 | 4.02k | let pkgs = generate::Generator::new(config.clone()).generate(u)?; |
21 | 4.02k | let mut resolve = Resolve::default(); |
22 | 4.02k | resolve.all_features = true; |
23 | 4.02k | let mut last = None; |
24 | 7.18k | for pkg in pkgs { |
25 | 7.18k | log::trace!("appending package {:?}", pkg.name); |
26 | 7.18k | let group = pkg.sources.parse().unwrap(); |
27 | 7.18k | let id = match resolve.push_group(group) { |
28 | 7.16k | Ok(id) => id, |
29 | 21 | Err(e) => match e.kind() { |
30 | | ResolveErrorKind::InvalidTransitiveDependency { .. } => { |
31 | 21 | return Err(arbitrary::Error::IncorrectFormat); |
32 | | } |
33 | | ResolveErrorKind::ItemShadowing { .. } |
34 | | | ResolveErrorKind::StabilityMismatch { .. } => { |
35 | 0 | log::error!("{e}"); |
36 | 0 | return Err(arbitrary::Error::IncorrectFormat); |
37 | | } |
38 | | _ => { |
39 | 0 | panic!("bad wit parse: {e:?}") |
40 | | } |
41 | | }, |
42 | | }; |
43 | 7.16k | last = Some(id); |
44 | | } |
45 | 4.00k | let pkg = last.unwrap(); |
46 | | |
47 | 4.00k | let wasm = wit_component::encode(&resolve, pkg).expect("failed to encode WIT document"); |
48 | | |
49 | | // Handle disallowing `stream<char>` here vs not generating it to start |
50 | | // with as it's a bit easier to handle. |
51 | 4.00k | if let Err(e) = wasmparser::Validator::new_with_features(wasmparser::WasmFeatures::all()) |
52 | 4.00k | .validate_all(&wasm) |
53 | | { |
54 | 33 | if e.to_string() |
55 | 33 | .contains("`stream<char>` is not valid at this time") |
56 | | { |
57 | 33 | return Err(arbitrary::Error::IncorrectFormat); |
58 | 0 | } |
59 | 3.97k | } |
60 | 3.97k | Ok(wasm) |
61 | 4.02k | } |