Coverage Report

Created: 2026-01-22 08:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wit-smith/src/generate.rs
Line
Count
Source
1
use crate::config::Config;
2
use arbitrary::{Arbitrary, Result, Unstructured};
3
use indexmap::{IndexMap, IndexSet};
4
use semver::Version;
5
use std::collections::HashSet;
6
use std::collections::hash_map::{Entry, HashMap};
7
use std::collections::hash_set::Intersection;
8
use std::fmt::Write;
9
use std::hash::RandomState;
10
use std::mem;
11
use std::rc::Rc;
12
use std::str;
13
use wit_parser::*;
14
15
pub struct Generator {
16
    config: Config,
17
    packages: Packages,
18
    next_interface_id: u32,
19
}
20
21
#[derive(PartialEq, Eq, Hash)]
22
pub struct PackageWorldKey {
23
    package_name: String,
24
    world_name: String,
25
}
26
27
struct InterfaceGenerator<'a> {
28
    generator: &'a mut Generator,
29
    file: &'a mut File,
30
    unique_names: HashSet<String>,
31
    types_in_interface: Vec<Type>,
32
    package_name: &'a str,
33
    version: Option<Version>,
34
}
35
36
#[derive(Clone)]
37
struct Type {
38
    name: String,
39
    size: usize,
40
    is_resource: bool,
41
}
42
43
#[derive(Default)]
44
struct Packages {
45
    list: Vec<Package>,
46
    packages_with_interfaces: Vec<usize>,
47
    packages_with_worlds: Vec<usize>,
48
    package_unique_names: IndexMap<PackageWorldKey, HashSet<String>>,
49
}
50
51
impl Packages {
52
15.6k
    fn add_name(&mut self, package_name: String, world_name: String, name: String) {
53
15.6k
        let key = PackageWorldKey {
54
15.6k
            package_name,
55
15.6k
            world_name,
56
15.6k
        };
57
15.6k
        let world_names = self
58
15.6k
            .package_unique_names
59
15.6k
            .entry(key)
60
15.6k
            .or_insert_with(HashSet::new);
61
15.6k
        world_names.insert(name);
62
15.6k
    }
63
64
0
    fn contains_name(&self, package_name: String, world_name: String, name: &str) -> bool {
65
0
        let key = PackageWorldKey {
66
0
            package_name,
67
0
            world_name,
68
0
        };
69
0
        if let Some(world_names) = self.package_unique_names.get(&key) {
70
0
            return world_names.contains(name);
71
0
        }
72
0
        false
73
0
    }
74
75
0
    fn intersect(
76
0
        &self,
77
0
        current_world: PackageWorldKey,
78
0
        include_world: PackageWorldKey,
79
0
    ) -> Option<Intersection<'_, String, RandomState>> {
80
0
        let current_world_names = self.package_unique_names.get(&current_world);
81
0
        let include_world_names = self.package_unique_names.get(&include_world);
82
83
0
        if let (Some(current_world_names), Some(include_world_names)) =
84
0
            (current_world_names, include_world_names)
85
        {
86
0
            let intersection = current_world_names.intersection(include_world_names);
87
0
            if intersection.clone().count() > 0 {
88
0
                return Some(intersection);
89
0
            }
90
0
        }
91
92
0
        return None;
93
0
    }
94
}
95
96
pub struct Package {
97
    pub name: PackageName,
98
    pub sources: SourceMap,
99
    file: File,
100
}
101
102
#[derive(Clone, Debug)]
103
pub struct PackageName {
104
    pub namespace: String,
105
    pub name: String,
106
    pub version: Option<Version>,
107
}
108
109
impl Generator {
110
4.49k
    pub fn new(config: Config) -> Generator {
111
4.49k
        Generator {
112
4.49k
            config,
113
4.49k
            packages: Default::default(),
114
4.49k
            next_interface_id: 0,
115
4.49k
        }
116
4.49k
    }
117
118
4.49k
    pub fn generate(&mut self, u: &mut Unstructured<'_>) -> Result<Vec<Package>> {
119
4.49k
        let mut names = HashSet::new();
120
11.8k
        while self.packages.list.len() < self.config.max_packages
121
11.1k
            && (self.packages.list.is_empty() || u.arbitrary()?)
122
        {
123
7.33k
            let pkg = self.gen_package(u, &mut names)?;
124
7.33k
            let i = self.packages.list.len();
125
7.33k
            if pkg.file.interfaces.len() > 0 {
126
2.98k
                self.packages.packages_with_interfaces.push(i);
127
4.34k
            }
128
7.33k
            if pkg.file.worlds.len() > 0 {
129
5.22k
                self.packages.packages_with_worlds.push(i);
130
5.22k
            }
131
7.33k
            self.packages.list.push(pkg);
132
        }
133
4.49k
        Ok(mem::take(&mut self.packages.list))
134
4.49k
    }
135
136
7.33k
    fn gen_package(
137
7.33k
        &mut self,
138
7.33k
        u: &mut Unstructured<'_>,
139
7.33k
        names: &mut HashSet<String>,
140
7.33k
    ) -> Result<Package> {
141
7.33k
        let namespace = gen_unique_name(u, names)?;
142
7.33k
        let package_name = gen_unique_name(u, names)?;
143
144
7.33k
        let version = if u.arbitrary()? {
145
5.22k
            Some(gen_version(u)?)
146
        } else {
147
2.11k
            None
148
        };
149
7.33k
        let mut ret = Package {
150
7.33k
            name: PackageName {
151
7.33k
                namespace,
152
7.33k
                name: package_name.clone(),
153
7.33k
                version: version.clone(),
154
7.33k
            },
155
7.33k
            file: File::default(),
156
7.33k
            sources: SourceMap::new(),
157
7.33k
        };
158
159
0
        #[derive(Arbitrary, Clone)]
Unexecuted instantiation: <<wit_smith::generate::Generator>::gen_package::Generate as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Unexecuted instantiation: <<wit_smith::generate::Generator>::gen_package::Generate as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Unexecuted instantiation: <<wit_smith::generate::Generator>::gen_package::Generate as arbitrary::Arbitrary>::arbitrary::{closure#1}
160
        enum Generate {
161
            Interface,
162
            Use,
163
            World,
164
            Done,
165
        }
166
167
7.33k
        let mut items = 0;
168
7.33k
        let mut empty = true;
169
7.33k
        let mut files = vec![File::default()];
170
7.33k
        let mut package_names = HashSet::new();
171
7.33k
        log::debug!("===================== new package ====================");
172
47.8k
        while items < self.config.max_pkg_items {
173
41.6k
            items += 1;
174
41.6k
            let max = if files.len() < self.config.max_files_per_package {
175
29.6k
                files.len() + 1
176
            } else {
177
12.0k
                files.len()
178
            };
179
41.6k
            let i = u.int_in_range(0..=max)?;
180
41.6k
            let file = match files.get_mut(i) {
181
32.3k
                Some(file) => file,
182
                None => {
183
9.33k
                    files.push(ret.file.clone());
184
9.33k
                    files.last_mut().unwrap()
185
                }
186
            };
187
188
            // Only generate Use/Done if we've already generated a world or interface. This ensures
189
            // that we never generate empty packages, which aren't representable.
190
41.6k
            let generate = if empty {
191
11.7k
                u.choose(&[Generate::World, Generate::Interface])?.clone()
192
            } else {
193
29.9k
                u.arbitrary()?
194
            };
195
196
41.6k
            match generate {
197
                Generate::World => {
198
9.40k
                    let world_name =
199
9.40k
                        file.gen_unique_package_name(u, &mut package_names, DefinitionKind::World)?;
200
9.40k
                    log::debug!("new world `{world_name}` in {i}");
201
9.40k
                    let world =
202
9.40k
                        self.gen_world(u, &world_name, file, &package_name, version.clone())?;
203
9.40k
                    file.items.push(world);
204
205
                    // Insert the world at the package and file level, asserting
206
                    // uniqueness.
207
9.40k
                    assert!(ret.file.worlds.insert(world_name.clone()));
208
9.40k
                    assert!(file.worlds.insert(world_name.clone()));
209
9.40k
                    let prev = ret.file.namespace.insert(
210
9.40k
                        world_name.clone(),
211
9.40k
                        (DefinitionLevel::Package, DefinitionKind::World),
212
                    );
213
9.40k
                    assert!(prev.is_none());
214
215
                    // Insert the definition into all other files as well.
216
19.2k
                    for file in files.iter_mut() {
217
19.2k
                        if file.insert_definition(&world_name, DefinitionKind::World) {
218
9.78k
                            assert!(file.worlds.insert(world_name.clone()));
219
9.42k
                        }
220
                    }
221
222
9.40k
                    empty = false;
223
                }
224
                Generate::Interface => {
225
27.4k
                    let name = file.gen_unique_package_name(
226
27.4k
                        u,
227
27.4k
                        &mut package_names,
228
27.4k
                        DefinitionKind::Interface,
229
0
                    )?;
230
27.4k
                    log::debug!("new interface `{name}` in {i}");
231
27.4k
                    let id = self.next_interface_id;
232
27.4k
                    self.next_interface_id += 1;
233
27.4k
                    let (src, types) =
234
27.4k
                        self.gen_interface(u, Some(&name), file, &package_name, None, None)?;
235
27.4k
                    file.items.push(src);
236
27.4k
                    if types.is_empty() {
237
22.0k
                        continue;
238
5.39k
                    }
239
5.39k
                    let interface = FileInterface {
240
5.39k
                        name,
241
5.39k
                        id,
242
5.39k
                        types: Rc::new(types),
243
5.39k
                    };
244
245
                    // This interface is defined at the package level, and it
246
                    // must be unique.
247
5.39k
                    let prev = ret
248
5.39k
                        .file
249
5.39k
                        .interfaces
250
5.39k
                        .insert(interface.name.clone(), interface.clone());
251
5.39k
                    assert!(prev.is_none());
252
5.39k
                    let prev = ret.file.namespace.insert(
253
5.39k
                        interface.name.clone(),
254
5.39k
                        (DefinitionLevel::Package, DefinitionKind::Interface),
255
                    );
256
5.39k
                    assert!(prev.is_none());
257
258
                    // This is also defined at the file level, and it must be
259
                    // unique here too.
260
5.39k
                    let prev = file
261
5.39k
                        .interfaces
262
5.39k
                        .insert(interface.name.clone(), interface.clone());
263
5.39k
                    assert!(prev.is_none());
264
265
                    // Insert the definition into all other files as well.
266
13.0k
                    for file in files.iter_mut() {
267
13.0k
                        if file.insert_definition(&interface.name, DefinitionKind::Interface) {
268
7.65k
                            let prev = file
269
7.65k
                                .interfaces
270
7.65k
                                .insert(interface.name.clone(), interface.clone());
271
7.65k
                            assert!(prev.is_none());
272
5.41k
                        }
273
                    }
274
275
5.39k
                    empty = false;
276
                }
277
                Generate::Use => {
278
3.59k
                    let mut piece = String::new();
279
3.59k
                    piece.push_str("use ");
280
2.64k
                    let (name, id, types) =
281
3.59k
                        match self.gen_interface_path(u, &mut ret.file, &mut piece)? {
282
2.64k
                            Some(i) => i,
283
948
                            None => continue,
284
                        };
285
2.64k
                    let name = name.to_string();
286
2.64k
                    let types = types.clone();
287
                    // If this interface's name already exist within this `file`
288
                    // then this must be renamed with `as`. If the name exists
289
                    // only at the package level then it's ok to replace it with
290
                    // something else.
291
                    //
292
                    // If the name doesn't exist then use the fuzz input to
293
                    // determine whether a rename should happen.
294
2.64k
                    let name =
295
2.64k
                        if matches!(file.namespace.get(&name), Some((DefinitionLevel::File, _)))
296
1.27k
                            || u.arbitrary()?
297
                        {
298
2.27k
                            let name = file.gen_unique_file_name(u, DefinitionKind::Interface)?;
299
2.27k
                            piece.push_str(" as %");
300
2.27k
                            piece.push_str(&name);
301
2.27k
                            name
302
                        } else {
303
374
                            file.namespace.insert(
304
374
                                name.clone(),
305
374
                                (DefinitionLevel::File, DefinitionKind::Interface),
306
                            );
307
374
                            name
308
                        };
309
2.64k
                    piece.push_str(";");
310
2.64k
                    log::debug!("new use `{name}` in {i}");
311
2.64k
                    file.worlds.swap_remove(&name);
312
2.64k
                    file.interfaces
313
2.64k
                        .insert(name.clone(), FileInterface { name, id, types });
314
2.64k
                    file.items.push(piece)
315
                }
316
1.22k
                Generate::Done => break,
317
            };
318
        }
319
320
7.33k
        shuffle(u, &mut files)?;
321
16.6k
        for file in files.iter_mut() {
322
16.6k
            shuffle(u, &mut file.items)?;
323
        }
324
325
7.33k
        let mut has_name = false;
326
7.33k
        let len = files.len();
327
16.6k
        for (i, file) in files.iter_mut().enumerate() {
328
16.6k
            let mut s = String::new();
329
16.6k
            if u.arbitrary()? || (!has_name && i == len - 1) {
330
10.8k
                has_name = true;
331
10.8k
                s.push_str("package ");
332
10.8k
                s.push_str("%");
333
10.8k
                s.push_str(&ret.name.namespace);
334
10.8k
                s.push_str(":");
335
10.8k
                s.push_str("%");
336
10.8k
                s.push_str(&ret.name.name);
337
10.8k
                if let Some(version) = &ret.name.version {
338
8.02k
                    s.push_str(&format!("@{version}"));
339
8.02k
                }
340
10.8k
                s.push_str(";\n\n");
341
5.79k
            }
342
39.5k
            for piece in file.items.iter() {
343
39.5k
                s.push_str(&piece);
344
39.5k
                s.push_str("\n\n");
345
39.5k
            }
346
16.6k
            log::trace!("===============================================");
347
16.6k
            log::trace!("{s}");
348
16.6k
            ret.sources.push(format!("wit{i}.wit").as_ref(), &s);
349
        }
350
7.33k
        Ok(ret)
351
7.33k
    }
352
353
9.40k
    fn gen_world(
354
9.40k
        &mut self,
355
9.40k
        u: &mut Unstructured<'_>,
356
9.40k
        name: &str,
357
9.40k
        file: &mut File,
358
9.40k
        package_name: &str,
359
9.40k
        version: Option<Version>,
360
9.40k
    ) -> Result<String> {
361
9.40k
        InterfaceGenerator::new(self, file, package_name, version).gen_world(u, name)
362
9.40k
    }
363
364
27.4k
    fn gen_interface(
365
27.4k
        &mut self,
366
27.4k
        u: &mut Unstructured<'_>,
367
27.4k
        name: Option<&str>,
368
27.4k
        file: &mut File,
369
27.4k
        package_name: &str,
370
27.4k
        world_name: Option<&str>,
371
27.4k
        version: Option<Version>,
372
27.4k
    ) -> Result<(String, Vec<Type>)> {
373
27.4k
        let mut generator = InterfaceGenerator::new(self, file, package_name, version);
374
27.4k
        let ret = generator.gen_interface(u, name, world_name)?;
375
27.4k
        Ok((ret, generator.types_in_interface))
376
27.4k
    }
377
378
88.0k
    fn gen_interface_path<'a>(
379
88.0k
        &'a self,
380
88.0k
        u: &mut Unstructured<'_>,
381
88.0k
        file: &'a mut File,
382
88.0k
        dst: &mut String,
383
88.0k
    ) -> Result<Option<(&'a str, u32, &'a Rc<Vec<Type>>)>> {
384
        enum Choice {
385
            Interfaces,
386
            Packages,
387
        }
388
88.0k
        let mut choices = Vec::new();
389
88.0k
        if !file.interfaces.is_empty() {
390
11.0k
            choices.push(Choice::Interfaces);
391
76.9k
        }
392
88.0k
        if !self.packages.packages_with_interfaces.is_empty() {
393
9.80k
            choices.push(Choice::Packages);
394
78.2k
        }
395
396
88.0k
        if choices.is_empty() {
397
74.3k
            return Ok(None);
398
13.7k
        }
399
13.7k
        Ok(match u.choose(&choices)? {
400
            Choice::Interfaces => {
401
4.56k
                let i = u.int_in_range(0..=file.interfaces.len() - 1)?;
402
4.56k
                let (name, i) = file.interfaces.get_index(i).unwrap();
403
                // Once a name is used from a file's local namespace then it
404
                // can't be overridden in that namespace so switch it to a file
405
                // definition from whatever it previously was.
406
4.56k
                file.namespace.insert(
407
4.56k
                    name.clone(),
408
4.56k
                    (DefinitionLevel::File, DefinitionKind::Interface),
409
                );
410
4.56k
                file.worlds.swap_remove(name);
411
4.56k
                dst.push_str("%");
412
4.56k
                dst.push_str(&i.name);
413
4.56k
                Some((&i.name, i.id, &i.types))
414
            }
415
            Choice::Packages => {
416
9.14k
                let pkg = u.choose(&self.packages.packages_with_interfaces)?;
417
9.14k
                let pkg = &self.packages.list[*pkg];
418
9.14k
                dst.push_str("%");
419
9.14k
                dst.push_str(&pkg.name.namespace);
420
9.14k
                dst.push_str(":");
421
9.14k
                dst.push_str("%");
422
9.14k
                dst.push_str(&pkg.name.name);
423
9.14k
                dst.push_str("/");
424
9.14k
                let i = u.int_in_range(0..=pkg.file.interfaces.len() - 1)?;
425
9.14k
                let i = &pkg.file.interfaces[i];
426
9.14k
                dst.push_str("%");
427
9.14k
                dst.push_str(&i.name);
428
9.14k
                if let Some(version) = &pkg.name.version {
429
7.98k
                    dst.push_str(&format!("@{version}"));
430
7.98k
                }
431
9.14k
                Some((&i.name, i.id, &i.types))
432
            }
433
        })
434
88.0k
    }
435
436
0
    fn gen_world_path<'a>(
437
0
        &'a self,
438
0
        u: &mut Unstructured<'_>,
439
0
        file: &'a mut File,
440
0
        dst: &mut String,
441
0
        includes: &mut HashSet<String>,
442
0
    ) -> Result<WorldPath<'a>> {
443
        enum Choice {
444
            Worlds,
445
            Packages,
446
        }
447
0
        let mut choices = Vec::new();
448
0
        if !file.worlds.is_empty() {
449
0
            choices.push(Choice::Worlds);
450
0
        }
451
0
        if !self.packages.packages_with_worlds.is_empty() {
452
0
            choices.push(Choice::Packages);
453
0
        }
454
455
0
        if choices.is_empty() {
456
0
            return Ok(WorldPath::None);
457
0
        }
458
0
        Ok(match u.choose(&choices)? {
459
            Choice::Worlds => {
460
0
                let i = u.int_in_range(0..=file.worlds.len() - 1)?;
461
0
                let name = &file.worlds[i];
462
463
0
                if !includes.insert(name.to_string()) {
464
0
                    return Ok(WorldPath::None);
465
0
                }
466
467
0
                dst.push_str("%");
468
0
                dst.push_str(&name);
469
                // Same as `gen_interface_path`, once a name is used as a world
470
                // it's forced to always be a world so update its definition to
471
                // be a file-level world.
472
473
0
                file.namespace
474
0
                    .insert(name.clone(), (DefinitionLevel::File, DefinitionKind::World));
475
0
                WorldPath::Local(name)
476
            }
477
            Choice::Packages => {
478
0
                let pkg = u.choose(&self.packages.packages_with_worlds)?;
479
0
                let pkg = &self.packages.list[*pkg];
480
0
                dst.push_str("%");
481
0
                dst.push_str(&pkg.name.namespace);
482
0
                dst.push_str(":");
483
0
                dst.push_str("%");
484
0
                dst.push_str(&pkg.name.name);
485
0
                dst.push_str("/");
486
0
                let i = u.int_in_range(0..=pkg.file.worlds.len() - 1)?;
487
0
                let w = &pkg.file.worlds[i];
488
0
                dst.push_str("%");
489
0
                dst.push_str(&w);
490
0
                if let Some(version) = &pkg.name.version {
491
0
                    dst.push_str(&format!("@{version}"));
492
0
                }
493
0
                WorldPath::Remote
494
            }
495
        })
496
0
    }
497
}
498
499
impl<'a> InterfaceGenerator<'a> {
500
38.4k
    fn new(
501
38.4k
        generator: &'a mut Generator,
502
38.4k
        file: &'a mut File,
503
38.4k
        package_name: &'a str,
504
38.4k
        version: Option<Version>,
505
38.4k
    ) -> InterfaceGenerator<'a> {
506
38.4k
        InterfaceGenerator {
507
38.4k
            generator,
508
38.4k
            file,
509
38.4k
            types_in_interface: Vec::new(),
510
38.4k
            // Claim the name `memory` to avoid conflicting with the canonical
511
38.4k
            // ABI always using a linear memory named `memory`.
512
38.4k
            unique_names: HashSet::from_iter(["memory".to_string()]),
513
38.4k
            package_name: package_name,
514
38.4k
            version,
515
38.4k
        }
516
38.4k
    }
517
518
    // Generate a feature gate annotation (@since, @unstable, or @deprecated)
519
    // If version is provided, ensures the annotation is compatible with the version
520
153k
    fn gen_feature_annotation(&self, u: &mut Unstructured<'_>) -> Result<Option<String>> {
521
153k
        if u.arbitrary()? {
522
125k
            return Ok(None);
523
28.4k
        }
524
525
28.4k
        let feature_names = ["active", "inactive"];
526
0
        #[derive(Arbitrary)]
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_feature_annotation::AnnotationType as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_feature_annotation::AnnotationType as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_feature_annotation::AnnotationType as arbitrary::Arbitrary>::arbitrary::{closure#1}
527
        enum AnnotationType {
528
            Since,
529
            Unstable,
530
            Deprecated,
531
        }
532
533
28.4k
        match self.version {
534
            None => {
535
                // No package version available
536
25.2k
                return Ok(None);
537
            }
538
3.21k
            Some(_) => match u.arbitrary()? {
539
                AnnotationType::Since => {
540
1.66k
                    let v = gen_version_less_than(u, &self.version)?;
541
1.66k
                    Ok(Some(format!("@since(version = {v})")))
542
                }
543
                AnnotationType::Unstable => {
544
756
                    let feature = u.choose(&feature_names)?;
545
756
                    Ok(Some(format!("@unstable(feature = {feature})")))
546
                }
547
                AnnotationType::Deprecated => {
548
788
                    let depreciation_version = gen_version_less_than(u, &self.version)?;
549
788
                    let since_version =
550
788
                        gen_version_less_than(u, &Some(depreciation_version.clone()))?;
551
788
                    Ok(Some(format!(
552
788
                        "@deprecated(version = {depreciation_version})\n@since(version = {since_version})",
553
788
                    )))
554
                }
555
            },
556
        }
557
153k
    }
558
559
29.0k
    fn gen_interface(
560
29.0k
        &mut self,
561
29.0k
        u: &mut Unstructured<'_>,
562
29.0k
        name: Option<&str>,
563
29.0k
        world_name: Option<&str>,
564
29.0k
    ) -> Result<String> {
565
29.0k
        let mut ret = String::new();
566
567
29.0k
        if let Some(annotation) = self.gen_feature_annotation(u)? {
568
0
            ret.push_str(&annotation);
569
0
            ret.push_str("\n");
570
29.0k
        }
571
572
29.0k
        ret.push_str("interface ");
573
29.0k
        if let Some(name) = name {
574
27.4k
            ret.push_str("%");
575
27.4k
            ret.push_str(name);
576
27.4k
            ret.push_str(" ");
577
27.4k
        }
578
29.0k
        ret.push_str("{\n");
579
580
0
        #[derive(Arbitrary)]
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_interface::Generate as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_interface::Generate as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_interface::Generate as arbitrary::Arbitrary>::arbitrary::{closure#1}
581
        enum Generate {
582
            Use,
583
            Type,
584
            Function,
585
        }
586
587
29.0k
        let mut parts = Vec::new();
588
129k
        while parts.len() < self.generator.config.max_interface_items && u.arbitrary()? {
589
100k
            let mut part = String::new();
590
100k
            if let Some(annotation) = self.gen_feature_annotation(u)? {
591
0
                part.push_str(&annotation);
592
0
                part.push_str("\n");
593
100k
            }
594
595
100k
            match u.arbitrary()? {
596
                Generate::Use => {
597
80.2k
                    if !self.gen_use(u, &mut part, world_name)? {
598
70.5k
                        continue;
599
9.71k
                    }
600
                }
601
                Generate::Type => {
602
12.2k
                    let name = self.gen_unique_name(u)?;
603
12.2k
                    let ty = self.gen_typedef(u, &name, &mut part)?;
604
12.2k
                    let is_resource = ty.is_resource;
605
12.2k
                    self.types_in_interface.push(ty);
606
12.2k
                    if is_resource {
607
937
                        if u.arbitrary()? {
608
586
                            part.push_str(" {\n");
609
586
                            self.gen_resource_funcs(&name, u, &mut part)?;
610
586
                            part.push_str("}");
611
351
                        } else {
612
351
                            part.push_str(";");
613
351
                        }
614
11.2k
                    }
615
                }
616
                Generate::Function => {
617
7.76k
                    self.gen_func(u, &mut part)?;
618
                }
619
            }
620
29.6k
            parts.push(part);
621
        }
622
623
29.0k
        shuffle(u, &mut parts)?;
624
58.7k
        for part in parts {
625
29.6k
            ret.push_str(&part);
626
29.6k
            ret.push_str("\n\n");
627
29.6k
        }
628
629
29.0k
        ret.push_str("}");
630
29.0k
        Ok(ret)
631
29.0k
    }
632
633
9.40k
    fn gen_world(&mut self, u: &mut Unstructured<'_>, world_name: &str) -> Result<String> {
634
9.40k
        let mut ret = String::new();
635
9.40k
        ret.push_str("world %");
636
9.40k
        ret.push_str(world_name);
637
9.40k
        ret.push_str(" {\n");
638
639
0
        #[derive(Arbitrary, Copy, Clone, Debug)]
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_world::Direction as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_world::Direction as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_world::Direction as arbitrary::Arbitrary>::arbitrary::{closure#1}
640
        enum Direction {
641
            Import,
642
            Export,
643
        }
644
645
0
        #[derive(Arbitrary)]
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_world::ItemKind as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_world::ItemKind as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_world::ItemKind as arbitrary::Arbitrary>::arbitrary::{closure#1}
646
        enum ItemKind {
647
            Func(Direction),
648
            Interface(Direction),
649
            AnonInterface(Direction),
650
            Type,
651
            Use,
652
            Include,
653
        }
654
655
9.40k
        let mut parts = Vec::new();
656
9.40k
        let mut imported_interfaces = HashSet::new();
657
9.40k
        let mut exported_interfaces = HashSet::new();
658
9.40k
        let mut includes: HashSet<String> = HashSet::new();
659
660
        // Claim the name `memory` to avoid conflicting with the canonical
661
        // ABI always using a linear memory named `memory`.
662
9.40k
        let mut export_names = HashSet::from_iter(["memory".to_string()]);
663
664
31.7k
        while parts.len() < self.generator.config.max_world_items
665
28.3k
            && !u.is_empty()
666
26.4k
            && u.arbitrary()?
667
        {
668
22.3k
            let kind = u.arbitrary::<ItemKind>()?;
669
22.3k
            let (direction, named) = match kind {
670
3.46k
                ItemKind::Func(dir) | ItemKind::AnonInterface(dir) => (Some(dir), true),
671
1.18k
                ItemKind::Interface(dir) => (Some(dir), false),
672
11.1k
                ItemKind::Type => (None, true),
673
2.95k
                ItemKind::Use => (None, false),
674
3.57k
                ItemKind::Include => (None, false),
675
            };
676
677
22.3k
            let mut part = String::new();
678
679
22.3k
            if let Some(annotation) = self.gen_feature_annotation(u)? {
680
3.09k
                part.push_str(&annotation);
681
3.09k
                part.push_str("\n");
682
19.2k
            }
683
684
22.3k
            if let Some(dir) = direction {
685
4.64k
                part.push_str(match dir {
686
3.09k
                    Direction::Import => "import ",
687
1.54k
                    Direction::Export => "export ",
688
                });
689
17.7k
            }
690
691
22.3k
            let name = if named {
692
14.6k
                let names = match direction {
693
13.4k
                    Some(Direction::Import) | None => &mut self.unique_names,
694
1.21k
                    Some(Direction::Export) => &mut export_names,
695
                };
696
14.6k
                let mut name = gen_unique_name(u, names)?;
697
698
                // check to see if any includes have a name clash, if so regenerate the name
699
                // this does have potential to throw away add a few names but that should be fine
700
14.6k
                for i in includes.iter() {
701
0
                    if self.generator.packages.contains_name(
702
0
                        self.package_name.to_string(),
703
0
                        i.to_string(),
704
0
                        &name,
705
                    ) {
706
0
                        name = gen_unique_name(u, names)?;
707
0
                    }
708
                }
709
710
14.6k
                if direction.is_some() {
711
3.46k
                    part.push_str("%");
712
3.46k
                    part.push_str(&name);
713
3.46k
                    part.push_str(": ");
714
11.1k
                }
715
716
14.6k
                self.generator.packages.add_name(
717
14.6k
                    self.package_name.to_string(),
718
14.6k
                    world_name.to_string(),
719
14.6k
                    name.to_string(),
720
                );
721
14.6k
                Some(name)
722
            } else {
723
7.72k
                None
724
            };
725
726
22.3k
            match kind {
727
                ItemKind::Func(_) => {
728
1.87k
                    self.gen_func_sig(u, &mut part, false)?;
729
                }
730
1.18k
                ItemKind::Interface(dir) => {
731
1.18k
                    let id = match self.generator.gen_interface_path(u, self.file, &mut part)? {
732
386
                        Some((_name, id, _types)) => id,
733
                        // If an interface couldn't be chosen or wasn't
734
                        // chosen then skip this import. A unique name was
735
                        // selecteed above but we just sort of leave that
736
                        // floating in the wild to get handled by some other
737
                        // test case.
738
799
                        None => continue,
739
                    };
740
741
                    // If this interface has already been imported or
742
                    // exported this document can't do so again. Throw out
743
                    // this item in that situation.
744
386
                    let unique = match dir {
745
262
                        Direction::Import => imported_interfaces.insert(id),
746
124
                        Direction::Export => exported_interfaces.insert(id),
747
                    };
748
386
                    if !unique {
749
69
                        continue;
750
317
                    }
751
317
                    part.push_str(";");
752
                }
753
                ItemKind::AnonInterface(_) => {
754
1.58k
                    let iface =
755
1.58k
                        InterfaceGenerator::new(self.generator, self.file, self.package_name, None)
756
1.58k
                            .gen_interface(u, None, Some(world_name))?;
757
1.58k
                    part.push_str(&iface);
758
                }
759
760
                ItemKind::Type => {
761
11.1k
                    let name = name.unwrap();
762
11.1k
                    let ty = self.gen_typedef(u, &name, &mut part)?;
763
11.1k
                    let is_resource = ty.is_resource;
764
11.1k
                    self.types_in_interface.push(ty);
765
766
11.1k
                    if is_resource {
767
382
                        if u.arbitrary()? {
768
294
                            part.push_str(" {\n");
769
294
                            self.gen_resource_funcs(&name, u, &mut part)?;
770
294
                            part.push_str("}");
771
88
                        } else {
772
88
                            part.push_str(";");
773
88
                        }
774
10.7k
                    }
775
                }
776
777
                ItemKind::Use => {
778
2.95k
                    if !self.gen_use(u, &mut part, Some(world_name))? {
779
1.99k
                        continue;
780
968
                    }
781
                }
782
783
                ItemKind::Include => {
784
3.57k
                    if !self.generator.config.world_include {
785
3.57k
                        continue;
786
0
                    }
787
0
                    part.push_str("include ");
788
0
                    match self
789
0
                        .generator
790
0
                        .gen_world_path(u, self.file, &mut part, &mut includes)?
791
                    {
792
0
                        WorldPath::Local(name) => {
793
                            // rename things if there is an naming conflict with
794
                            // the include and the world we are going into this
795
                            // is a best effort, there are some edge cases where
796
                            // we might not catch something in that case we just
797
                            // throw away the generated world for fuzzing
798
0
                            let current_world = PackageWorldKey {
799
0
                                package_name: self.package_name.to_owned(),
800
0
                                world_name: world_name.to_owned(),
801
0
                            };
802
0
                            let include_world = PackageWorldKey {
803
0
                                package_name: self.package_name.to_owned(),
804
0
                                world_name: name.to_owned(),
805
0
                            };
806
0
                            let intersection = self
807
0
                                .generator
808
0
                                .packages
809
0
                                .intersect(current_world, include_world);
810
0
                            if let Some(names) = intersection {
811
0
                                part.push_str(" with { %");
812
813
0
                                for n in names {
814
0
                                    part.push_str(n);
815
0
                                    part.push_str(" as %");
816
                                    // we know it is in one of the worlds, lets
817
                                    // add it here just for good measure
818
0
                                    self.unique_names.insert(n.to_string());
819
0
                                    let new_name = gen_unique_name(u, &mut self.unique_names)?;
820
0
                                    part.push_str(&new_name);
821
0
                                    part.push_str(",");
822
                                }
823
0
                                part.push_str("}");
824
0
                            } else {
825
0
                                // ; is only used if not renaming
826
0
                                part.push_str(";");
827
0
                            }
828
                        }
829
0
                        WorldPath::Remote => {
830
0
                            part.push_str(";");
831
0
                        }
832
0
                        WorldPath::None => continue,
833
                    };
834
                }
835
            }
836
15.9k
            parts.push(part);
837
        }
838
839
9.40k
        shuffle(u, &mut parts)?;
840
841
25.3k
        for part in parts {
842
15.9k
            ret.push_str(&part);
843
15.9k
            ret.push_str("\n");
844
15.9k
        }
845
846
9.40k
        ret.push_str("}");
847
848
9.40k
        Ok(ret)
849
9.40k
    }
850
851
880
    fn gen_resource_funcs(
852
880
        &mut self,
853
880
        resource_name: &str,
854
880
        u: &mut Unstructured<'_>,
855
880
        ret: &mut String,
856
880
    ) -> Result<()> {
857
880
        let mut parts = Vec::new();
858
859
0
        #[derive(Arbitrary)]
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_resource_funcs::Item as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_resource_funcs::Item as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_resource_funcs::Item as arbitrary::Arbitrary>::arbitrary::{closure#1}
860
        enum Item {
861
            Constructor,
862
            Static,
863
            Method,
864
        }
865
866
880
        let mut has_constructor = false;
867
880
        let mut names = HashSet::new();
868
880
        names.insert(resource_name.to_string());
869
3.30k
        while parts.len() < self.generator.config.max_resource_items
870
2.99k
            && !u.is_empty()
871
2.84k
            && u.arbitrary()?
872
        {
873
2.42k
            match u.arbitrary()? {
874
336
                Item::Constructor if has_constructor => {}
875
                Item::Constructor => {
876
275
                    has_constructor = true;
877
275
                    let mut part = String::new();
878
879
275
                    if let Some(annotation) = self.gen_feature_annotation(u)? {
880
34
                        part.push_str(&annotation);
881
34
                        part.push_str("\n");
882
241
                    }
883
884
275
                    part.push_str("constructor");
885
275
                    self.gen_params(u, &mut part, false)?;
886
275
                    part.push_str(";");
887
275
                    parts.push(part);
888
                }
889
                Item::Static => {
890
745
                    let mut part = String::new();
891
892
745
                    if let Some(annotation) = self.gen_feature_annotation(u)? {
893
57
                        part.push_str(&annotation);
894
57
                        part.push_str("\n");
895
688
                    }
896
897
745
                    part.push_str("%");
898
745
                    part.push_str(&gen_unique_name(u, &mut names)?);
899
745
                    part.push_str(": static ");
900
745
                    self.gen_func_sig(u, &mut part, false)?;
901
745
                    parts.push(part);
902
                }
903
                Item::Method => {
904
1.06k
                    let mut part = String::new();
905
906
1.06k
                    if let Some(annotation) = self.gen_feature_annotation(u)? {
907
25
                        part.push_str(&annotation);
908
25
                        part.push_str("\n");
909
1.04k
                    }
910
911
1.06k
                    part.push_str("%");
912
1.06k
                    part.push_str(&gen_unique_name(u, &mut names)?);
913
1.06k
                    part.push_str(": ");
914
1.06k
                    self.gen_func_sig(u, &mut part, true)?;
915
1.06k
                    parts.push(part);
916
                }
917
            }
918
        }
919
920
880
        shuffle(u, &mut parts)?;
921
922
2.96k
        for part in parts {
923
2.08k
            ret.push_str(&part);
924
2.08k
            ret.push_str("\n");
925
2.08k
        }
926
880
        Ok(())
927
880
    }
928
929
83.2k
    fn gen_use(
930
83.2k
        &mut self,
931
83.2k
        u: &mut Unstructured<'_>,
932
83.2k
        part: &mut String,
933
83.2k
        world_name: Option<&str>,
934
83.2k
    ) -> Result<bool> {
935
83.2k
        let mut path = String::new();
936
10.6k
        let (_name, _id, types) =
937
83.2k
            match self.generator.gen_interface_path(u, self.file, &mut path)? {
938
10.6k
                Some(types) => types,
939
72.5k
                None => return Ok(false),
940
            };
941
10.6k
        part.push_str("use ");
942
10.6k
        part.push_str(&path);
943
10.6k
        part.push_str(".{");
944
10.6k
        let ty = u.choose(types)?;
945
10.6k
        part.push_str("%");
946
10.6k
        part.push_str(&ty.name);
947
10.6k
        let size = ty.size;
948
10.6k
        let is_resource = ty.is_resource;
949
10.6k
        let name = if self.unique_names.contains(&ty.name) || u.arbitrary()? {
950
9.63k
            part.push_str(" as %");
951
9.63k
            let name = self.gen_unique_name(u)?;
952
9.63k
            part.push_str(&name);
953
            // if we name something then we need track it at the package level for includes
954
9.63k
            if let Some(world_name) = world_name {
955
1.04k
                self.generator.packages.add_name(
956
1.04k
                    self.package_name.to_string(),
957
1.04k
                    world_name.to_string(),
958
1.04k
                    name.to_string(),
959
1.04k
                );
960
8.58k
            }
961
9.63k
            name
962
        } else {
963
1.04k
            assert!(self.unique_names.insert(ty.name.clone()));
964
1.04k
            ty.name.clone()
965
        };
966
10.6k
        self.types_in_interface.push(Type {
967
10.6k
            name,
968
10.6k
            size,
969
10.6k
            is_resource,
970
10.6k
        });
971
10.6k
        part.push_str("};");
972
10.6k
        Ok(true)
973
83.2k
    }
974
975
23.3k
    fn gen_typedef(
976
23.3k
        &mut self,
977
23.3k
        u: &mut Unstructured<'_>,
978
23.3k
        name: &str,
979
23.3k
        ret: &mut String,
980
23.3k
    ) -> Result<Type> {
981
0
        #[derive(Arbitrary)]
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_typedef::Kind as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_typedef::Kind as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_typedef::Kind as arbitrary::Arbitrary>::arbitrary::{closure#1}
982
        pub enum Kind {
983
            Record,
984
            Flags,
985
            Variant,
986
            Enum,
987
            Anonymous,
988
            Resource,
989
        }
990
991
23.3k
        let mut fuel = self.generator.config.max_type_size;
992
993
23.3k
        let mut is_resource = false;
994
23.3k
        match u.arbitrary()? {
995
            Kind::Record => {
996
2.39k
                ret.push_str("record %");
997
2.39k
                ret.push_str(name);
998
2.39k
                ret.push_str(" {\n");
999
2.39k
                for _ in 0..u.int_in_range(1..=self.generator.config.max_type_parts)? {
1000
6.30k
                    ret.push_str("  %");
1001
6.30k
                    ret.push_str(&self.gen_unique_name(u)?);
1002
6.30k
                    ret.push_str(": ");
1003
6.30k
                    self.gen_type(u, &mut fuel, ret)?;
1004
6.30k
                    ret.push_str(",\n");
1005
                }
1006
2.39k
                ret.push_str("}");
1007
            }
1008
            Kind::Variant => {
1009
4.45k
                ret.push_str("variant %");
1010
4.45k
                ret.push_str(name);
1011
4.45k
                ret.push_str(" {\n");
1012
4.45k
                for _ in 0..u.int_in_range(1..=self.generator.config.max_type_parts)? {
1013
15.1k
                    ret.push_str("  %");
1014
15.1k
                    ret.push_str(&self.gen_unique_name(u)?);
1015
15.1k
                    if u.arbitrary()? {
1016
13.3k
                        ret.push_str("(");
1017
13.3k
                        self.gen_type(u, &mut fuel, ret)?;
1018
13.3k
                        ret.push_str(")");
1019
1.89k
                    }
1020
15.1k
                    ret.push_str(",\n");
1021
                }
1022
4.45k
                ret.push_str("}");
1023
            }
1024
            Kind::Enum => {
1025
13.4k
                ret.push_str("enum %");
1026
13.4k
                ret.push_str(name);
1027
13.4k
                ret.push_str(" {\n");
1028
13.4k
                for _ in 0..u.int_in_range(1..=self.generator.config.max_type_parts)? {
1029
58.8k
                    ret.push_str("  %");
1030
58.8k
                    ret.push_str(&self.gen_unique_name(u)?);
1031
58.8k
                    ret.push_str(",\n");
1032
                }
1033
13.4k
                ret.push_str("}");
1034
            }
1035
            Kind::Flags => {
1036
830
                ret.push_str("flags %");
1037
830
                ret.push_str(name);
1038
830
                ret.push_str(" {\n");
1039
830
                for _ in 0..u.int_in_range(1..=self.generator.config.max_type_parts)? {
1040
2.49k
                    ret.push_str("  %");
1041
2.49k
                    ret.push_str(&self.gen_unique_name(u)?);
1042
2.49k
                    ret.push_str(",\n");
1043
                }
1044
830
                ret.push_str("}");
1045
            }
1046
            Kind::Anonymous => {
1047
887
                ret.push_str("type %");
1048
887
                ret.push_str(name);
1049
887
                ret.push_str(" = ");
1050
887
                self.gen_type(u, &mut fuel, ret)?;
1051
887
                ret.push_str(";");
1052
            }
1053
1.31k
            Kind::Resource => {
1054
1.31k
                is_resource = true;
1055
1.31k
                ret.push_str("resource %");
1056
1.31k
                ret.push_str(name);
1057
1.31k
            }
1058
        }
1059
1060
23.3k
        Ok(Type {
1061
23.3k
            size: self.generator.config.max_type_size - fuel,
1062
23.3k
            is_resource,
1063
23.3k
            name: name.to_string(),
1064
23.3k
        })
1065
23.3k
    }
1066
1067
233k
    fn gen_type(
1068
233k
        &mut self,
1069
233k
        u: &mut Unstructured<'_>,
1070
233k
        fuel: &mut usize,
1071
233k
        dst: &mut String,
1072
233k
    ) -> Result<()> {
1073
0
        #[derive(Arbitrary)]
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_type::Kind as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_type::Kind as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Unexecuted instantiation: <<wit_smith::generate::InterfaceGenerator>::gen_type::Kind as arbitrary::Arbitrary>::arbitrary::{closure#1}
1074
        enum Kind {
1075
            Bool,
1076
            U8,
1077
            U16,
1078
            U32,
1079
            U64,
1080
            S8,
1081
            S16,
1082
            S32,
1083
            S64,
1084
            F32,
1085
            F64,
1086
            Char,
1087
            String,
1088
            Id,
1089
            Tuple,
1090
            Option,
1091
            Result,
1092
            List,
1093
            FixedLengthList,
1094
            Stream,
1095
            Future,
1096
            ErrorContext,
1097
        }
1098
1099
233k
        *fuel = match fuel.checked_sub(1) {
1100
205k
            Some(fuel) => fuel,
1101
            None => {
1102
28.0k
                dst.push_str("bool");
1103
28.0k
                return Ok(());
1104
            }
1105
        };
1106
        loop {
1107
222k
            break match u.arbitrary()? {
1108
14.7k
                Kind::Bool => dst.push_str("bool"),
1109
3.72k
                Kind::U8 => dst.push_str("u8"),
1110
1.48k
                Kind::S8 => dst.push_str("s8"),
1111
920
                Kind::U16 => dst.push_str("u16"),
1112
776
                Kind::S16 => dst.push_str("s16"),
1113
1.94k
                Kind::U32 => dst.push_str("u32"),
1114
1.23k
                Kind::S32 => dst.push_str("s32"),
1115
1.53k
                Kind::U64 => dst.push_str("u64"),
1116
7.28k
                Kind::S64 => dst.push_str("s64"),
1117
2.70k
                Kind::F32 => dst.push_str("f32"),
1118
5.42k
                Kind::F64 => dst.push_str("f64"),
1119
5.56k
                Kind::Char => dst.push_str("char"),
1120
1.12k
                Kind::String => dst.push_str("string"),
1121
                Kind::Id => {
1122
3.46k
                    if self.types_in_interface.is_empty() {
1123
2.05k
                        continue;
1124
1.40k
                    }
1125
1.40k
                    let ty = u.choose(&self.types_in_interface)?;
1126
1.40k
                    *fuel = match fuel.checked_sub(ty.size) {
1127
1.37k
                        Some(fuel) => fuel,
1128
26
                        None => continue,
1129
                    };
1130
1.37k
                    let own_wrapper = if ty.is_resource && u.arbitrary()? {
1131
350
                        dst.push_str("own<");
1132
350
                        true
1133
                    } else {
1134
1.02k
                        false
1135
                    };
1136
1.37k
                    dst.push_str("%");
1137
1.37k
                    dst.push_str(&ty.name);
1138
1.37k
                    if own_wrapper {
1139
350
                        dst.push_str(">");
1140
1.02k
                    }
1141
                }
1142
                Kind::Tuple => {
1143
9.78k
                    let fields = u.int_in_range(1..=self.generator.config.max_type_parts)?;
1144
9.78k
                    *fuel = match fuel.checked_sub(fields) {
1145
9.21k
                        Some(fuel) => fuel,
1146
568
                        None => continue,
1147
                    };
1148
9.21k
                    dst.push_str("tuple<");
1149
33.8k
                    for i in 0..fields {
1150
33.8k
                        if i > 0 {
1151
24.6k
                            dst.push_str(", ");
1152
24.6k
                        }
1153
33.8k
                        self.gen_type(u, fuel, dst)?;
1154
                    }
1155
9.21k
                    dst.push_str(">");
1156
                }
1157
                Kind::Option => {
1158
11.5k
                    *fuel = match fuel.checked_sub(1) {
1159
11.0k
                        Some(fuel) => fuel,
1160
512
                        None => continue,
1161
                    };
1162
11.0k
                    dst.push_str("option<");
1163
11.0k
                    self.gen_type(u, fuel, dst)?;
1164
11.0k
                    dst.push_str(">");
1165
                }
1166
                Kind::List => {
1167
3.50k
                    *fuel = match fuel.checked_sub(1) {
1168
2.86k
                        Some(fuel) => fuel,
1169
646
                        None => continue,
1170
                    };
1171
2.86k
                    dst.push_str("list<");
1172
2.86k
                    self.gen_type(u, fuel, dst)?;
1173
2.86k
                    dst.push_str(">");
1174
                }
1175
                Kind::FixedLengthList => {
1176
105k
                    if !self.generator.config.fixed_length_lists {
1177
623
                        continue;
1178
105k
                    }
1179
105k
                    *fuel = match fuel.checked_sub(1) {
1180
105k
                        Some(fuel) => fuel,
1181
59
                        None => continue,
1182
                    };
1183
105k
                    let elements =
1184
105k
                        u.int_in_range(1..=self.generator.config.max_type_parts as u32)?;
1185
105k
                    dst.push_str("list<");
1186
105k
                    self.gen_type(u, fuel, dst)?;
1187
105k
                    dst.push_str(&format!(", {elements}>"));
1188
                }
1189
                Kind::Result => {
1190
13.0k
                    *fuel = match fuel.checked_sub(2) {
1191
12.5k
                        Some(fuel) => fuel,
1192
488
                        None => continue,
1193
                    };
1194
12.5k
                    dst.push_str("result");
1195
12.5k
                    let ok = u.arbitrary()?;
1196
12.5k
                    let err = u.arbitrary()?;
1197
12.5k
                    match (ok, err) {
1198
                        (true, true) => {
1199
9.42k
                            dst.push_str("<");
1200
9.42k
                            self.gen_type(u, fuel, dst)?;
1201
9.42k
                            dst.push_str(", ");
1202
9.42k
                            self.gen_type(u, fuel, dst)?;
1203
9.42k
                            dst.push_str(">");
1204
                        }
1205
                        (true, false) => {
1206
1.78k
                            dst.push_str("<");
1207
1.78k
                            self.gen_type(u, fuel, dst)?;
1208
1.78k
                            dst.push_str(">");
1209
                        }
1210
                        (false, true) => {
1211
1.09k
                            dst.push_str("<_, ");
1212
1.09k
                            self.gen_type(u, fuel, dst)?;
1213
1.09k
                            dst.push_str(">");
1214
                        }
1215
271
                        (false, false) => {}
1216
                    }
1217
                }
1218
                Kind::Stream => {
1219
3.34k
                    if !self.generator.config.streams {
1220
1.02k
                        continue;
1221
2.32k
                    }
1222
2.32k
                    *fuel = match fuel.checked_sub(1) {
1223
2.28k
                        Some(fuel) => fuel,
1224
44
                        None => continue,
1225
                    };
1226
2.28k
                    dst.push_str("stream<");
1227
2.28k
                    self.gen_type(u, fuel, dst)?;
1228
2.28k
                    dst.push_str(">");
1229
                }
1230
                Kind::Future => {
1231
4.62k
                    if !self.generator.config.futures {
1232
1.44k
                        continue;
1233
3.17k
                    }
1234
3.17k
                    *fuel = match fuel.checked_sub(1) {
1235
3.03k
                        Some(fuel) => fuel,
1236
142
                        None => continue,
1237
                    };
1238
3.03k
                    if u.arbitrary()? {
1239
1.70k
                        dst.push_str("future<");
1240
1.70k
                        self.gen_type(u, fuel, dst)?;
1241
1.70k
                        dst.push_str(">");
1242
1.32k
                    } else {
1243
1.32k
                        dst.push_str("future");
1244
1.32k
                    }
1245
                }
1246
                Kind::ErrorContext => {
1247
18.7k
                    if !self.generator.config.error_context {
1248
9.39k
                        continue;
1249
9.38k
                    }
1250
9.38k
                    dst.push_str("error-context");
1251
                }
1252
            };
1253
        }
1254
1255
205k
        Ok(())
1256
233k
    }
1257
1258
7.76k
    fn gen_func(&mut self, u: &mut Unstructured<'_>, ret: &mut String) -> Result<()> {
1259
7.76k
        ret.push_str("%");
1260
7.76k
        ret.push_str(&self.gen_unique_name(u)?);
1261
7.76k
        ret.push_str(": ");
1262
7.76k
        self.gen_func_sig(u, ret, false)?;
1263
7.76k
        Ok(())
1264
7.76k
    }
1265
1266
11.4k
    fn gen_func_sig(
1267
11.4k
        &mut self,
1268
11.4k
        u: &mut Unstructured<'_>,
1269
11.4k
        dst: &mut String,
1270
11.4k
        method: bool,
1271
11.4k
    ) -> Result<()> {
1272
11.4k
        if self.generator.config.async_ && u.arbitrary()? {
1273
6.49k
            dst.push_str("async ");
1274
6.49k
        }
1275
11.4k
        dst.push_str("func");
1276
11.4k
        self.gen_params(u, dst, method)?;
1277
11.4k
        if u.arbitrary()? {
1278
8.29k
            dst.push_str(" -> ");
1279
8.29k
            let mut fuel = self.generator.config.max_type_size;
1280
8.29k
            self.gen_type(u, &mut fuel, dst)?;
1281
3.15k
        }
1282
11.4k
        dst.push_str(";");
1283
11.4k
        Ok(())
1284
11.4k
    }
1285
1286
11.7k
    fn gen_params(
1287
11.7k
        &mut self,
1288
11.7k
        u: &mut Unstructured<'_>,
1289
11.7k
        dst: &mut String,
1290
11.7k
        method: bool,
1291
11.7k
    ) -> Result<()> {
1292
11.7k
        dst.push_str("(");
1293
11.7k
        let mut names = HashSet::new();
1294
11.7k
        if method {
1295
1.06k
            names.insert("self".to_string());
1296
10.6k
        }
1297
11.7k
        let mut fuel = self.generator.config.max_type_size;
1298
26.0k
        for i in 0..u.int_in_range(0..=self.generator.config.max_type_parts)? {
1299
26.0k
            if i > 0 {
1300
16.8k
                dst.push_str(", ");
1301
16.8k
            }
1302
26.0k
            dst.push_str("%");
1303
26.0k
            dst.push_str(&gen_unique_name(u, &mut names)?);
1304
26.0k
            dst.push_str(": ");
1305
26.0k
            self.gen_type(u, &mut fuel, dst)?;
1306
        }
1307
11.7k
        dst.push_str(")");
1308
11.7k
        Ok(())
1309
11.7k
    }
1310
1311
112k
    fn gen_unique_name(&mut self, u: &mut Unstructured<'_>) -> Result<String> {
1312
112k
        gen_unique_name(u, &mut self.unique_names)
1313
112k
    }
1314
}
1315
1316
169k
fn gen_unique_name(u: &mut Unstructured<'_>, set: &mut HashSet<String>) -> Result<String> {
1317
169k
    let mut name = gen_name(u)?;
1318
293k
    while !set.insert(name.clone()) {
1319
123k
        write!(&mut name, "{}", set.len()).unwrap();
1320
123k
    }
1321
169k
    Ok(name)
1322
169k
}
1323
1324
208k
fn gen_name(u: &mut Unstructured<'_>) -> Result<String> {
1325
208k
    let size = u.arbitrary_len::<u8>()?;
1326
208k
    let size = std::cmp::min(size, 20);
1327
208k
    let name = match str::from_utf8(u.peek_bytes(size).unwrap()) {
1328
65.5k
        Ok(s) => {
1329
65.5k
            u.bytes(size).unwrap();
1330
65.5k
            s.to_string()
1331
        }
1332
143k
        Err(e) => {
1333
143k
            let i = e.valid_up_to();
1334
143k
            let valid = u.bytes(i).unwrap();
1335
143k
            str::from_utf8(valid).unwrap().to_string()
1336
        }
1337
    };
1338
208k
    let name = name
1339
208k
        .chars()
1340
758k
        .map(|x| if x.is_ascii_lowercase() { x } else { 'x' })
1341
208k
        .collect::<String>();
1342
208k
    Ok(if name.is_empty() {
1343
150k
        "name".to_string()
1344
    } else {
1345
58.2k
        name
1346
    })
1347
208k
}
1348
1349
63.3k
fn shuffle<T>(u: &mut Unstructured<'_>, mut slice: &mut [T]) -> Result<()> {
1350
167k
    while slice.len() > 0 {
1351
103k
        let pos = u.int_in_range(0..=slice.len() - 1)?;
1352
103k
        slice.swap(0, pos);
1353
103k
        slice = &mut slice[1..];
1354
    }
1355
63.3k
    Ok(())
1356
63.3k
}
wit_smith::generate::shuffle::<wit_smith::generate::File>
Line
Count
Source
1349
7.33k
fn shuffle<T>(u: &mut Unstructured<'_>, mut slice: &mut [T]) -> Result<()> {
1350
24.0k
    while slice.len() > 0 {
1351
16.6k
        let pos = u.int_in_range(0..=slice.len() - 1)?;
1352
16.6k
        slice.swap(0, pos);
1353
16.6k
        slice = &mut slice[1..];
1354
    }
1355
7.33k
    Ok(())
1356
7.33k
}
wit_smith::generate::shuffle::<alloc::string::String>
Line
Count
Source
1349
56.0k
fn shuffle<T>(u: &mut Unstructured<'_>, mut slice: &mut [T]) -> Result<()> {
1350
143k
    while slice.len() > 0 {
1351
87.1k
        let pos = u.int_in_range(0..=slice.len() - 1)?;
1352
87.1k
        slice.swap(0, pos);
1353
87.1k
        slice = &mut slice[1..];
1354
    }
1355
56.0k
    Ok(())
1356
56.0k
}
1357
1358
#[derive(Clone, Default)]
1359
struct File {
1360
    items: Vec<String>,
1361
    namespace: HashMap<String, (DefinitionLevel, DefinitionKind)>,
1362
    interfaces: IndexMap<String, FileInterface>,
1363
    worlds: IndexSet<String>,
1364
}
1365
1366
#[derive(Clone)]
1367
struct FileInterface {
1368
    name: String,
1369
    id: u32,
1370
    types: Rc<Vec<Type>>,
1371
}
1372
1373
#[derive(Debug, Copy, Clone, PartialEq)]
1374
enum DefinitionLevel {
1375
    Package,
1376
    File,
1377
}
1378
1379
#[derive(Debug, Copy, Clone, PartialEq)]
1380
enum DefinitionKind {
1381
    World,
1382
    Interface,
1383
}
1384
1385
enum WorldPath<'a> {
1386
    None,
1387
    Local(&'a str),
1388
    Remote,
1389
}
1390
1391
impl File {
1392
36.8k
    fn gen_unique_package_name(
1393
36.8k
        &mut self,
1394
36.8k
        u: &mut Unstructured<'_>,
1395
36.8k
        names: &mut HashSet<String>,
1396
36.8k
        kind: DefinitionKind,
1397
36.8k
    ) -> Result<String> {
1398
36.8k
        let mut name = gen_name(u)?;
1399
        loop {
1400
            // Find a package-unique name first
1401
61.0k
            if !names.insert(name.clone()) {
1402
24.2k
                write!(&mut name, "{}", names.len()).unwrap();
1403
24.2k
                continue;
1404
36.8k
            }
1405
1406
            // Then make sure it's file-unique too
1407
36.8k
            if self.claim_file_name(&mut name, kind) {
1408
36.8k
                break;
1409
17
            }
1410
        }
1411
36.8k
        Ok(name)
1412
36.8k
    }
1413
1414
2.27k
    fn gen_unique_file_name(
1415
2.27k
        &mut self,
1416
2.27k
        u: &mut Unstructured<'_>,
1417
2.27k
        kind: DefinitionKind,
1418
2.27k
    ) -> Result<String> {
1419
2.27k
        let mut name = gen_name(u)?;
1420
3.47k
        while !self.claim_file_name(&mut name, kind) {
1421
1.19k
            // try again on the next iteration
1422
1.19k
        }
1423
2.27k
        Ok(name)
1424
2.27k
    }
1425
1426
40.3k
    fn claim_file_name(&mut self, name: &mut String, kind: DefinitionKind) -> bool {
1427
40.3k
        match self.namespace.entry(name.clone()) {
1428
1.40k
            Entry::Occupied(mut e) => match e.get().0 {
1429
                // If this name is already claimed elsewhere in the package
1430
                // then that's ok as we're going to shadow it, so switch it
1431
                // to a file definition.
1432
189
                DefinitionLevel::Package => *e.get_mut() = (DefinitionLevel::File, kind),
1433
1434
                // If it's already defined in the file try to add more stuff
1435
                // to the name to make the next try not collide.
1436
                DefinitionLevel::File => {
1437
1.21k
                    name.push_str("y");
1438
1.21k
                    write!(name, "{}", self.namespace.len()).unwrap();
1439
1.21k
                    return false;
1440
                }
1441
            },
1442
1443
            // Not defined? Claim it.
1444
38.9k
            Entry::Vacant(v) => {
1445
38.9k
                v.insert((DefinitionLevel::File, kind));
1446
38.9k
            }
1447
        }
1448
39.1k
        true
1449
40.3k
    }
1450
1451
32.2k
    fn insert_definition(&mut self, name: &str, kind: DefinitionKind) -> bool {
1452
32.2k
        match self.namespace.get(name) {
1453
            // This name is already defined, so it can't be inserted.
1454
14.8k
            Some((DefinitionLevel::File, _)) => return false,
1455
0
            Some(other) => {
1456
0
                panic!("found duplicate definition when should be package-unique: {other:?}")
1457
            }
1458
17.4k
            None => {}
1459
        }
1460
17.4k
        let prev = self
1461
17.4k
            .namespace
1462
17.4k
            .insert(name.to_string(), (DefinitionLevel::Package, kind));
1463
17.4k
        assert!(prev.is_none());
1464
17.4k
        true
1465
32.2k
    }
1466
}
1467
1468
8.46k
fn gen_version_less_than(
1469
8.46k
    u: &mut Unstructured<'_>,
1470
8.46k
    existing_version: &Option<Version>,
1471
8.46k
) -> Result<Version> {
1472
    const MAX_VERSION_RANGE: u64 = 10;
1473
8.46k
    let (major, minor, patch) = match existing_version {
1474
3.24k
        Some(v) => (v.major, v.minor, v.patch),
1475
5.22k
        None => (MAX_VERSION_RANGE, MAX_VERSION_RANGE, MAX_VERSION_RANGE),
1476
    };
1477
1478
8.46k
    let new_version = Version {
1479
8.46k
        major: u.int_in_range(0..=major)?,
1480
8.46k
        minor: u.int_in_range(0..=minor)?,
1481
8.46k
        patch: u.int_in_range(0..=patch)?,
1482
8.46k
        pre: if (u.arbitrary()? && existing_version.is_none())
1483
4.56k
            || existing_version.as_ref().is_some_and(|x| !x.pre.is_empty())
1484
        {
1485
6.24k
            semver::Prerelease::new("alpha.0").unwrap()
1486
        } else {
1487
2.21k
            semver::Prerelease::EMPTY
1488
        },
1489
8.46k
        build: if (u.arbitrary()? && existing_version.is_none())
1490
4.75k
            || existing_version
1491
4.75k
                .as_ref()
1492
4.75k
                .is_some_and(|x| !x.build.is_empty())
1493
        {
1494
5.72k
            semver::BuildMetadata::new("1.2.0").unwrap()
1495
        } else {
1496
2.73k
            semver::BuildMetadata::EMPTY
1497
        },
1498
    };
1499
1500
8.46k
    if let Some(v) = existing_version {
1501
3.24k
        assert!(&new_version <= v, "{} <= {}", &new_version, v);
1502
5.22k
    }
1503
1504
8.46k
    Ok(new_version)
1505
8.46k
}
1506
1507
5.22k
fn gen_version(u: &mut Unstructured<'_>) -> Result<Version> {
1508
5.22k
    gen_version_less_than(u, &None)
1509
5.22k
}