Coverage Report

Created: 2026-09-14 07:40

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
35.2k
    fn add_name(&mut self, package_name: String, world_name: String, name: String) {
53
35.2k
        let key = PackageWorldKey {
54
35.2k
            package_name,
55
35.2k
            world_name,
56
35.2k
        };
57
35.2k
        let world_names = self
58
35.2k
            .package_unique_names
59
35.2k
            .entry(key)
60
35.2k
            .or_insert_with(HashSet::new);
61
35.2k
        world_names.insert(name);
62
35.2k
    }
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.46k
    pub fn new(config: Config) -> Generator {
111
4.46k
        Generator {
112
4.46k
            config,
113
4.46k
            packages: Default::default(),
114
4.46k
            next_interface_id: 0,
115
4.46k
        }
116
4.46k
    }
117
118
4.46k
    pub fn generate(&mut self, u: &mut Unstructured<'_>) -> Result<Vec<Package>> {
119
4.46k
        let mut names = HashSet::new();
120
12.2k
        while self.packages.list.len() < self.config.max_packages
121
11.6k
            && (self.packages.list.is_empty() || u.arbitrary()?)
122
        {
123
7.80k
            let pkg = self.gen_package(u, &mut names)?;
124
7.80k
            let i = self.packages.list.len();
125
7.80k
            if pkg.file.interfaces.len() > 0 {
126
3.91k
                self.packages.packages_with_interfaces.push(i);
127
3.91k
            }
128
7.80k
            if pkg.file.worlds.len() > 0 {
129
5.38k
                self.packages.packages_with_worlds.push(i);
130
5.38k
            }
131
7.80k
            self.packages.list.push(pkg);
132
        }
133
4.46k
        Ok(mem::take(&mut self.packages.list))
134
4.46k
    }
135
136
7.80k
    fn gen_package(
137
7.80k
        &mut self,
138
7.80k
        u: &mut Unstructured<'_>,
139
7.80k
        names: &mut HashSet<String>,
140
7.80k
    ) -> Result<Package> {
141
7.80k
        let namespace = gen_unique_name(u, names)?;
142
7.80k
        let package_name = gen_unique_name(u, names)?;
143
144
7.80k
        let version = if u.arbitrary()? {
145
5.95k
            Some(gen_version(u)?)
146
        } else {
147
1.84k
            None
148
        };
149
7.80k
        let mut ret = Package {
150
7.80k
            name: PackageName {
151
7.80k
                namespace,
152
7.80k
                name: package_name.clone(),
153
7.80k
                version: version.clone(),
154
7.80k
            },
155
7.80k
            file: File::default(),
156
7.80k
            sources: SourceMap::new(),
157
7.80k
        };
158
159
        #[derive(Arbitrary, Clone)]
160
        enum Generate {
161
            Interface,
162
            Use,
163
            World,
164
            Done,
165
        }
166
167
7.80k
        let mut items = 0;
168
7.80k
        let mut empty = true;
169
7.80k
        let mut files = vec![File::default()];
170
7.80k
        let mut package_names = HashSet::new();
171
7.80k
        log::debug!("===================== new package ====================");
172
54.0k
        while items < self.config.max_pkg_items {
173
47.6k
            items += 1;
174
47.6k
            let max = if files.len() < self.config.max_files_per_package {
175
33.5k
                files.len() + 1
176
            } else {
177
14.1k
                files.len()
178
            };
179
47.6k
            let i = u.int_in_range(0..=max)?;
180
47.6k
            let file = match files.get_mut(i) {
181
37.1k
                Some(file) => file,
182
                None => {
183
10.5k
                    files.push(ret.file.clone());
184
10.5k
                    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
47.6k
            let generate = if empty {
191
12.2k
                u.choose(&[Generate::World, Generate::Interface])?.clone()
192
            } else {
193
35.4k
                u.arbitrary()?
194
            };
195
196
47.6k
            match generate {
197
                Generate::World => {
198
12.0k
                    let world_name =
199
12.0k
                        file.gen_unique_package_name(u, &mut package_names, DefinitionKind::World)?;
200
12.0k
                    log::debug!("new world `{world_name}` in {i}");
201
12.0k
                    let world =
202
12.0k
                        self.gen_world(u, &world_name, file, &package_name, version.clone())?;
203
12.0k
                    file.items.push(world);
204
205
                    // Insert the world at the package and file level, asserting
206
                    // uniqueness.
207
12.0k
                    assert!(ret.file.worlds.insert(world_name.clone()));
208
12.0k
                    assert!(file.worlds.insert(world_name.clone()));
209
12.0k
                    let prev = ret.file.namespace.insert(
210
12.0k
                        world_name.clone(),
211
12.0k
                        (DefinitionLevel::Package, DefinitionKind::World),
212
                    );
213
12.0k
                    assert!(prev.is_none());
214
215
                    // Insert the definition into all other files as well.
216
24.1k
                    for file in files.iter_mut() {
217
24.1k
                        if file.insert_definition(&world_name, DefinitionKind::World) {
218
12.1k
                            assert!(file.worlds.insert(world_name.clone()));
219
12.0k
                        }
220
                    }
221
222
12.0k
                    empty = false;
223
                }
224
                Generate::Interface => {
225
29.5k
                    let name = file.gen_unique_package_name(
226
29.5k
                        u,
227
29.5k
                        &mut package_names,
228
29.5k
                        DefinitionKind::Interface,
229
0
                    )?;
230
29.5k
                    log::debug!("new interface `{name}` in {i}");
231
29.5k
                    let id = self.next_interface_id;
232
29.5k
                    self.next_interface_id += 1;
233
29.5k
                    let (src, types) =
234
29.5k
                        self.gen_interface(u, Some(&name), file, &package_name, None, None)?;
235
29.5k
                    file.items.push(src);
236
29.5k
                    if types.is_empty() {
237
21.9k
                        continue;
238
7.56k
                    }
239
7.56k
                    let interface = FileInterface {
240
7.56k
                        name,
241
7.56k
                        id,
242
7.56k
                        types: Rc::new(types),
243
7.56k
                    };
244
245
                    // This interface is defined at the package level, and it
246
                    // must be unique.
247
7.56k
                    let prev = ret
248
7.56k
                        .file
249
7.56k
                        .interfaces
250
7.56k
                        .insert(interface.name.clone(), interface.clone());
251
7.56k
                    assert!(prev.is_none());
252
7.56k
                    let prev = ret.file.namespace.insert(
253
7.56k
                        interface.name.clone(),
254
7.56k
                        (DefinitionLevel::Package, DefinitionKind::Interface),
255
                    );
256
7.56k
                    assert!(prev.is_none());
257
258
                    // This is also defined at the file level, and it must be
259
                    // unique here too.
260
7.56k
                    let prev = file
261
7.56k
                        .interfaces
262
7.56k
                        .insert(interface.name.clone(), interface.clone());
263
7.56k
                    assert!(prev.is_none());
264
265
                    // Insert the definition into all other files as well.
266
18.1k
                    for file in files.iter_mut() {
267
18.1k
                        if file.insert_definition(&interface.name, DefinitionKind::Interface) {
268
10.5k
                            let prev = file
269
10.5k
                                .interfaces
270
10.5k
                                .insert(interface.name.clone(), interface.clone());
271
10.5k
                            assert!(prev.is_none());
272
7.57k
                        }
273
                    }
274
275
7.56k
                    empty = false;
276
                }
277
                Generate::Use => {
278
4.67k
                    let mut piece = String::new();
279
4.67k
                    piece.push_str("use ");
280
3.66k
                    let (name, id, types) =
281
4.67k
                        match self.gen_interface_path(u, &mut ret.file, &mut piece)? {
282
3.66k
                            Some(i) => i,
283
1.00k
                            None => continue,
284
                        };
285
3.66k
                    let name = name.to_string();
286
3.66k
                    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
3.66k
                    let name =
295
3.66k
                        if matches!(file.namespace.get(&name), Some((DefinitionLevel::File, _)))
296
1.79k
                            || u.arbitrary()?
297
                        {
298
3.32k
                            let name = file.gen_unique_file_name(u, DefinitionKind::Interface)?;
299
3.32k
                            piece.push_str(" as %");
300
3.32k
                            piece.push_str(&name);
301
3.32k
                            name
302
                        } else {
303
338
                            file.namespace.insert(
304
338
                                name.clone(),
305
338
                                (DefinitionLevel::File, DefinitionKind::Interface),
306
                            );
307
338
                            name
308
                        };
309
3.66k
                    piece.push_str(";");
310
3.66k
                    log::debug!("new use `{name}` in {i}");
311
3.66k
                    file.worlds.swap_remove(&name);
312
3.66k
                    file.interfaces
313
3.66k
                        .insert(name.clone(), FileInterface { name, id, types });
314
3.66k
                    file.items.push(piece)
315
                }
316
1.46k
                Generate::Done => break,
317
            };
318
        }
319
320
7.80k
        shuffle(u, &mut files)?;
321
18.3k
        for file in files.iter_mut() {
322
18.3k
            shuffle(u, &mut file.items)?;
323
        }
324
325
7.80k
        let mut has_name = false;
326
7.80k
        let len = files.len();
327
18.3k
        for (i, file) in files.iter_mut().enumerate() {
328
18.3k
            let mut s = String::new();
329
18.3k
            if u.arbitrary()? || (!has_name && i == len - 1) {
330
12.5k
                has_name = true;
331
12.5k
                s.push_str("package ");
332
12.5k
                s.push_str("%");
333
12.5k
                s.push_str(&ret.name.namespace);
334
12.5k
                s.push_str(":");
335
12.5k
                s.push_str("%");
336
12.5k
                s.push_str(&ret.name.name);
337
12.5k
                if let Some(version) = &ret.name.version {
338
9.96k
                    s.push_str(&format!("@{version}"));
339
9.96k
                }
340
12.5k
                s.push_str(";\n\n");
341
5.79k
            }
342
45.2k
            for piece in file.items.iter() {
343
45.2k
                s.push_str(&piece);
344
45.2k
                s.push_str("\n\n");
345
45.2k
            }
346
18.3k
            log::trace!("===============================================");
347
18.3k
            log::trace!("{s}");
348
18.3k
            ret.sources.push(format!("wit{i}.wit").as_ref(), &s);
349
        }
350
7.80k
        Ok(ret)
351
7.80k
    }
352
353
12.0k
    fn gen_world(
354
12.0k
        &mut self,
355
12.0k
        u: &mut Unstructured<'_>,
356
12.0k
        name: &str,
357
12.0k
        file: &mut File,
358
12.0k
        package_name: &str,
359
12.0k
        version: Option<Version>,
360
12.0k
    ) -> Result<String> {
361
12.0k
        InterfaceGenerator::new(self, file, package_name, version).gen_world(u, name)
362
12.0k
    }
363
364
29.5k
    fn gen_interface(
365
29.5k
        &mut self,
366
29.5k
        u: &mut Unstructured<'_>,
367
29.5k
        name: Option<&str>,
368
29.5k
        file: &mut File,
369
29.5k
        package_name: &str,
370
29.5k
        world_name: Option<&str>,
371
29.5k
        version: Option<Version>,
372
29.5k
    ) -> Result<(String, Vec<Type>)> {
373
29.5k
        let mut generator = InterfaceGenerator::new(self, file, package_name, version);
374
29.5k
        let ret = generator.gen_interface(u, name, world_name)?;
375
29.5k
        Ok((ret, generator.types_in_interface))
376
29.5k
    }
377
378
111k
    fn gen_interface_path<'a>(
379
111k
        &'a self,
380
111k
        u: &mut Unstructured<'_>,
381
111k
        file: &'a mut File,
382
111k
        dst: &mut String,
383
111k
    ) -> Result<Option<(&'a str, u32, &'a Rc<Vec<Type>>)>> {
384
        enum Choice {
385
            Interfaces,
386
            Packages,
387
        }
388
111k
        let mut choices = Vec::new();
389
111k
        if !file.interfaces.is_empty() {
390
46.4k
            choices.push(Choice::Interfaces);
391
64.7k
        }
392
111k
        if !self.packages.packages_with_interfaces.is_empty() {
393
38.7k
            choices.push(Choice::Packages);
394
72.4k
        }
395
396
111k
        if choices.is_empty() {
397
59.8k
            return Ok(None);
398
51.3k
        }
399
51.3k
        Ok(match u.choose(&choices)? {
400
            Choice::Interfaces => {
401
13.5k
                let i = u.int_in_range(0..=file.interfaces.len() - 1)?;
402
13.5k
                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
13.5k
                file.namespace.insert(
407
13.5k
                    name.clone(),
408
13.5k
                    (DefinitionLevel::File, DefinitionKind::Interface),
409
                );
410
13.5k
                file.worlds.swap_remove(name);
411
13.5k
                dst.push_str("%");
412
13.5k
                dst.push_str(&i.name);
413
13.5k
                Some((&i.name, i.id, &i.types))
414
            }
415
            Choice::Packages => {
416
37.8k
                let pkg = u.choose(&self.packages.packages_with_interfaces)?;
417
37.8k
                let pkg = &self.packages.list[*pkg];
418
37.8k
                dst.push_str("%");
419
37.8k
                dst.push_str(&pkg.name.namespace);
420
37.8k
                dst.push_str(":");
421
37.8k
                dst.push_str("%");
422
37.8k
                dst.push_str(&pkg.name.name);
423
37.8k
                dst.push_str("/");
424
37.8k
                let i = u.int_in_range(0..=pkg.file.interfaces.len() - 1)?;
425
37.8k
                let i = &pkg.file.interfaces[i];
426
37.8k
                dst.push_str("%");
427
37.8k
                dst.push_str(&i.name);
428
37.8k
                if let Some(version) = &pkg.name.version {
429
35.8k
                    dst.push_str(&format!("@{version}"));
430
35.8k
                }
431
37.8k
                Some((&i.name, i.id, &i.types))
432
            }
433
        })
434
111k
    }
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
42.7k
    fn new(
501
42.7k
        generator: &'a mut Generator,
502
42.7k
        file: &'a mut File,
503
42.7k
        package_name: &'a str,
504
42.7k
        version: Option<Version>,
505
42.7k
    ) -> InterfaceGenerator<'a> {
506
42.7k
        InterfaceGenerator {
507
42.7k
            generator,
508
42.7k
            file,
509
42.7k
            types_in_interface: Vec::new(),
510
42.7k
            // Claim the name `memory` to avoid conflicting with the canonical
511
42.7k
            // ABI always using a linear memory named `memory`.
512
42.7k
            unique_names: HashSet::from_iter(["memory".to_string()]),
513
42.7k
            package_name: package_name,
514
42.7k
            version,
515
42.7k
        }
516
42.7k
    }
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
185k
    fn gen_feature_annotation(&self, u: &mut Unstructured<'_>) -> Result<Option<String>> {
521
185k
        if u.arbitrary()? {
522
156k
            return Ok(None);
523
29.5k
        }
524
525
29.5k
        let feature_names = ["active", "inactive"];
526
        #[derive(Arbitrary)]
527
        enum AnnotationType {
528
            Since,
529
            Unstable,
530
            Deprecated,
531
        }
532
533
29.5k
        match self.version {
534
            None => {
535
                // No package version available
536
25.4k
                return Ok(None);
537
            }
538
4.10k
            Some(_) => match u.arbitrary()? {
539
                AnnotationType::Since => {
540
1.73k
                    let v = gen_version_less_than(u, &self.version)?;
541
1.73k
                    Ok(Some(format!("@since(version = {v})")))
542
                }
543
                AnnotationType::Unstable => {
544
1.52k
                    let feature = u.choose(&feature_names)?;
545
1.52k
                    Ok(Some(format!("@unstable(feature = {feature})")))
546
                }
547
                AnnotationType::Deprecated => {
548
844
                    let depreciation_version = gen_version_less_than(u, &self.version)?;
549
844
                    let since_version =
550
844
                        gen_version_less_than(u, &Some(depreciation_version.clone()))?;
551
844
                    Ok(Some(format!(
552
844
                        "@deprecated(version = {depreciation_version})\n@since(version = {since_version})",
553
844
                    )))
554
                }
555
            },
556
        }
557
185k
    }
558
559
30.7k
    fn gen_interface(
560
30.7k
        &mut self,
561
30.7k
        u: &mut Unstructured<'_>,
562
30.7k
        name: Option<&str>,
563
30.7k
        world_name: Option<&str>,
564
30.7k
    ) -> Result<String> {
565
30.7k
        let mut ret = String::new();
566
567
30.7k
        if let Some(annotation) = self.gen_feature_annotation(u)? {
568
0
            ret.push_str(&annotation);
569
0
            ret.push_str("\n");
570
30.7k
        }
571
572
30.7k
        ret.push_str("interface ");
573
30.7k
        if let Some(name) = name {
574
29.5k
            ret.push_str("%");
575
29.5k
            ret.push_str(name);
576
29.5k
            ret.push_str(" ");
577
29.5k
        }
578
30.7k
        ret.push_str("{\n");
579
580
        #[derive(Arbitrary)]
581
        enum Generate {
582
            Use,
583
            Type,
584
            Function,
585
        }
586
587
30.7k
        let mut parts = Vec::new();
588
134k
        while parts.len() < self.generator.config.max_interface_items && u.arbitrary()? {
589
103k
            let mut part = String::new();
590
103k
            if let Some(annotation) = self.gen_feature_annotation(u)? {
591
0
                part.push_str(&annotation);
592
0
                part.push_str("\n");
593
103k
            }
594
595
103k
            if u.arbitrary()? {
596
97.9k
                part.push_str("@external-id(\"hi\")\n");
597
97.9k
            }
598
599
103k
            match u.arbitrary()? {
600
                Generate::Use => {
601
75.1k
                    if !self.gen_use(u, &mut part, world_name)? {
602
54.5k
                        continue;
603
20.6k
                    }
604
                }
605
                Generate::Type => {
606
15.1k
                    let name = self.gen_unique_name(u)?;
607
15.1k
                    let ty = self.gen_typedef(u, &name, &mut part)?;
608
15.1k
                    let is_resource = ty.is_resource;
609
15.1k
                    self.types_in_interface.push(ty);
610
15.1k
                    if is_resource {
611
1.14k
                        if u.arbitrary()? {
612
972
                            part.push_str(" {\n");
613
972
                            self.gen_resource_funcs(&name, u, &mut part)?;
614
972
                            part.push_str("}");
615
175
                        } else {
616
175
                            part.push_str(";");
617
175
                        }
618
14.0k
                    }
619
                }
620
                Generate::Function => {
621
13.4k
                    self.gen_func(u, &mut part)?;
622
                }
623
            }
624
49.2k
            parts.push(part);
625
        }
626
627
30.7k
        shuffle(u, &mut parts)?;
628
49.2k
        for part in parts {
629
49.2k
            ret.push_str(&part);
630
49.2k
            ret.push_str("\n\n");
631
49.2k
        }
632
633
30.7k
        ret.push_str("}");
634
30.7k
        Ok(ret)
635
30.7k
    }
636
637
12.0k
    fn gen_world(&mut self, u: &mut Unstructured<'_>, world_name: &str) -> Result<String> {
638
12.0k
        let mut ret = String::new();
639
12.0k
        ret.push_str("world %");
640
12.0k
        ret.push_str(world_name);
641
12.0k
        ret.push_str(" {\n");
642
643
        #[derive(Arbitrary, Copy, Clone, Debug)]
644
        enum Direction {
645
            Import,
646
            Export,
647
        }
648
649
        #[derive(Arbitrary)]
650
        enum ItemKind {
651
            Func(Direction),
652
            Interface(Direction),
653
            AnonInterface(Direction),
654
            ImplementsInterface(Direction),
655
            Type,
656
            Use,
657
            Include,
658
        }
659
660
12.0k
        let mut parts = Vec::new();
661
12.0k
        let mut imported_interfaces = HashSet::new();
662
12.0k
        let mut exported_interfaces = HashSet::new();
663
12.0k
        let mut includes: HashSet<String> = HashSet::new();
664
665
        // Claim the name `memory` to avoid conflicting with the canonical
666
        // ABI always using a linear memory named `memory`.
667
12.0k
        let mut export_names = HashSet::from_iter(["memory".to_string()]);
668
669
60.5k
        while parts.len() < self.generator.config.max_world_items
670
55.0k
            && !u.is_empty()
671
53.0k
            && u.arbitrary()?
672
        {
673
48.4k
            let kind = u.arbitrary::<ItemKind>()?;
674
675
            // Gate config-disabled features early, before consuming any
676
            // more random bytes, to keep byte consumption deterministic
677
            // when a feature is toggled off.
678
48.4k
            if matches!(kind, ItemKind::ImplementsInterface(_)) && !self.generator.config.implements
679
            {
680
934
                continue;
681
47.5k
            }
682
683
47.5k
            let (direction, named) = match kind {
684
4.01k
                ItemKind::Func(dir) | ItemKind::AnonInterface(dir) => (Some(dir), true),
685
29.7k
                ItemKind::Interface(dir) | ItemKind::ImplementsInterface(dir) => (Some(dir), false),
686
6.20k
                ItemKind::Type => (None, true),
687
1.67k
                ItemKind::Use => (None, false),
688
5.88k
                ItemKind::Include => (None, false),
689
            };
690
691
47.5k
            let mut part = String::new();
692
693
47.5k
            if let Some(annotation) = self.gen_feature_annotation(u)? {
694
4.00k
                part.push_str(&annotation);
695
4.00k
                part.push_str("\n");
696
43.5k
            }
697
698
47.5k
            if u.arbitrary()? {
699
42.8k
                part.push_str("@external-id(\"hi\")\n");
700
42.8k
            }
701
702
47.5k
            if let Some(dir) = direction {
703
33.7k
                part.push_str(match dir {
704
6.82k
                    Direction::Import => "import ",
705
26.9k
                    Direction::Export => "export ",
706
                });
707
13.7k
            }
708
709
47.5k
            let name = if named {
710
10.2k
                let names = match direction {
711
8.46k
                    Some(Direction::Import) | None => &mut self.unique_names,
712
1.76k
                    Some(Direction::Export) => &mut export_names,
713
                };
714
10.2k
                let mut name = gen_unique_name(u, names)?;
715
716
                // check to see if any includes have a name clash, if so regenerate the name
717
                // this does have potential to throw away add a few names but that should be fine
718
10.2k
                for i in includes.iter() {
719
0
                    if self.generator.packages.contains_name(
720
0
                        self.package_name.to_string(),
721
0
                        i.to_string(),
722
0
                        &name,
723
                    ) {
724
0
                        name = gen_unique_name(u, names)?;
725
0
                    }
726
                }
727
728
10.2k
                if direction.is_some() {
729
4.01k
                    part.push_str("%");
730
4.01k
                    part.push_str(&name);
731
4.01k
                    part.push_str(": ");
732
6.20k
                }
733
734
10.2k
                self.generator.packages.add_name(
735
10.2k
                    self.package_name.to_string(),
736
10.2k
                    world_name.to_string(),
737
10.2k
                    name.to_string(),
738
                );
739
10.2k
                Some(name)
740
            } else {
741
37.3k
                None
742
            };
743
744
47.5k
            match kind {
745
                ItemKind::Func(_) => {
746
2.77k
                    self.gen_func_sig(u, &mut part, false)?;
747
                }
748
4.34k
                ItemKind::Interface(dir) => {
749
4.34k
                    let id = match self.generator.gen_interface_path(u, self.file, &mut part)? {
750
2.41k
                        Some((_name, id, _types)) => id,
751
                        // If an interface couldn't be chosen or wasn't
752
                        // chosen then skip this import. A unique name was
753
                        // selecteed above but we just sort of leave that
754
                        // floating in the wild to get handled by some other
755
                        // test case.
756
1.93k
                        None => continue,
757
                    };
758
759
                    // If this interface has already been imported or
760
                    // exported this document can't do so again. Throw out
761
                    // this item in that situation.
762
2.41k
                    let unique = match dir {
763
1.71k
                        Direction::Import => imported_interfaces.insert(id),
764
696
                        Direction::Export => exported_interfaces.insert(id),
765
                    };
766
2.41k
                    if !unique {
767
1.94k
                        continue;
768
464
                    }
769
464
                    part.push_str(";");
770
                }
771
25.4k
                ItemKind::ImplementsInterface(dir) => {
772
25.4k
                    let names = match dir {
773
1.67k
                        Direction::Import => &mut self.unique_names,
774
23.7k
                        Direction::Export => &mut export_names,
775
                    };
776
25.4k
                    let label = gen_unique_name(u, names)?;
777
778
25.4k
                    let mut path_str = String::new();
779
25.4k
                    if self
780
25.4k
                        .generator
781
25.4k
                        .gen_interface_path(u, self.file, &mut path_str)?
782
25.4k
                        .is_none()
783
                    {
784
1.47k
                        continue;
785
23.9k
                    }
786
787
23.9k
                    self.generator.packages.add_name(
788
23.9k
                        self.package_name.to_string(),
789
23.9k
                        world_name.to_string(),
790
23.9k
                        label.to_string(),
791
                    );
792
793
23.9k
                    part.push_str("%");
794
23.9k
                    part.push_str(&label);
795
23.9k
                    part.push_str(": ");
796
23.9k
                    part.push_str(&path_str);
797
23.9k
                    part.push_str(";");
798
                }
799
                ItemKind::AnonInterface(_) => {
800
1.24k
                    let iface =
801
1.24k
                        InterfaceGenerator::new(self.generator, self.file, self.package_name, None)
802
1.24k
                            .gen_interface(u, None, Some(world_name))?;
803
1.24k
                    part.push_str(&iface);
804
                }
805
806
                ItemKind::Type => {
807
6.20k
                    let name = name.unwrap();
808
6.20k
                    let ty = self.gen_typedef(u, &name, &mut part)?;
809
6.20k
                    let is_resource = ty.is_resource;
810
6.20k
                    self.types_in_interface.push(ty);
811
812
6.20k
                    if is_resource {
813
504
                        if u.arbitrary()? {
814
426
                            part.push_str(" {\n");
815
426
                            self.gen_resource_funcs(&name, u, &mut part)?;
816
426
                            part.push_str("}");
817
78
                        } else {
818
78
                            part.push_str(";");
819
78
                        }
820
5.70k
                    }
821
                }
822
823
                ItemKind::Use => {
824
1.67k
                    if !self.gen_use(u, &mut part, Some(world_name))? {
825
962
                        continue;
826
714
                    }
827
                }
828
829
                ItemKind::Include => {
830
5.88k
                    if !self.generator.config.world_include {
831
5.88k
                        continue;
832
0
                    }
833
0
                    part.push_str("include ");
834
0
                    match self
835
0
                        .generator
836
0
                        .gen_world_path(u, self.file, &mut part, &mut includes)?
837
                    {
838
0
                        WorldPath::Local(name) => {
839
                            // rename things if there is an naming conflict with
840
                            // the include and the world we are going into this
841
                            // is a best effort, there are some edge cases where
842
                            // we might not catch something in that case we just
843
                            // throw away the generated world for fuzzing
844
0
                            let current_world = PackageWorldKey {
845
0
                                package_name: self.package_name.to_owned(),
846
0
                                world_name: world_name.to_owned(),
847
0
                            };
848
0
                            let include_world = PackageWorldKey {
849
0
                                package_name: self.package_name.to_owned(),
850
0
                                world_name: name.to_owned(),
851
0
                            };
852
0
                            let intersection = self
853
0
                                .generator
854
0
                                .packages
855
0
                                .intersect(current_world, include_world);
856
0
                            if let Some(names) = intersection {
857
0
                                part.push_str(" with { %");
858
859
0
                                for n in names {
860
0
                                    part.push_str(n);
861
0
                                    part.push_str(" as %");
862
                                    // we know it is in one of the worlds, lets
863
                                    // add it here just for good measure
864
0
                                    self.unique_names.insert(n.to_string());
865
0
                                    let new_name = gen_unique_name(u, &mut self.unique_names)?;
866
0
                                    part.push_str(&new_name);
867
0
                                    part.push_str(",");
868
                                }
869
0
                                part.push_str("}");
870
0
                            } else {
871
0
                                // ; is only used if not renaming
872
0
                                part.push_str(";");
873
0
                            }
874
                        }
875
0
                        WorldPath::Remote => {
876
0
                            part.push_str(";");
877
0
                        }
878
0
                        WorldPath::None => continue,
879
                    };
880
                }
881
            }
882
35.3k
            parts.push(part);
883
        }
884
885
12.0k
        shuffle(u, &mut parts)?;
886
887
35.3k
        for part in parts {
888
35.3k
            ret.push_str(&part);
889
35.3k
            ret.push_str("\n");
890
35.3k
        }
891
892
12.0k
        ret.push_str("}");
893
894
12.0k
        Ok(ret)
895
12.0k
    }
896
897
1.39k
    fn gen_resource_funcs(
898
1.39k
        &mut self,
899
1.39k
        resource_name: &str,
900
1.39k
        u: &mut Unstructured<'_>,
901
1.39k
        ret: &mut String,
902
1.39k
    ) -> Result<()> {
903
1.39k
        let mut parts = Vec::new();
904
905
        #[derive(Arbitrary)]
906
        enum Item {
907
            Constructor,
908
            Static,
909
            Method,
910
        }
911
912
1.39k
        let mut has_constructor = false;
913
1.39k
        let mut names = HashSet::new();
914
1.39k
        names.insert(resource_name.to_string());
915
5.38k
        while parts.len() < self.generator.config.max_resource_items
916
4.92k
            && !u.is_empty()
917
4.76k
            && u.arbitrary()?
918
        {
919
3.99k
            match u.arbitrary()? {
920
466
                Item::Constructor if has_constructor => {}
921
                Item::Constructor => {
922
455
                    has_constructor = true;
923
455
                    let mut part = String::new();
924
925
455
                    if let Some(annotation) = self.gen_feature_annotation(u)? {
926
34
                        part.push_str(&annotation);
927
34
                        part.push_str("\n");
928
421
                    }
929
930
455
                    part.push_str("constructor");
931
455
                    self.gen_params(u, &mut part, false)?;
932
455
                    part.push_str(";");
933
455
                    parts.push(part);
934
                }
935
                Item::Static => {
936
1.15k
                    let mut part = String::new();
937
938
1.15k
                    if let Some(annotation) = self.gen_feature_annotation(u)? {
939
16
                        part.push_str(&annotation);
940
16
                        part.push_str("\n");
941
1.13k
                    }
942
943
1.15k
                    part.push_str("%");
944
1.15k
                    part.push_str(&gen_unique_name(u, &mut names)?);
945
1.15k
                    part.push_str(": static ");
946
1.15k
                    self.gen_func_sig(u, &mut part, false)?;
947
1.15k
                    parts.push(part);
948
                }
949
                Item::Method => {
950
1.92k
                    let mut part = String::new();
951
952
1.92k
                    if let Some(annotation) = self.gen_feature_annotation(u)? {
953
45
                        part.push_str(&annotation);
954
45
                        part.push_str("\n");
955
1.87k
                    }
956
957
1.92k
                    part.push_str("%");
958
1.92k
                    part.push_str(&gen_unique_name(u, &mut names)?);
959
1.92k
                    part.push_str(": ");
960
1.92k
                    self.gen_func_sig(u, &mut part, true)?;
961
1.92k
                    parts.push(part);
962
                }
963
            }
964
        }
965
966
1.39k
        shuffle(u, &mut parts)?;
967
968
3.52k
        for part in parts {
969
3.52k
            ret.push_str(&part);
970
3.52k
            ret.push_str("\n");
971
3.52k
        }
972
1.39k
        Ok(())
973
1.39k
    }
974
975
76.8k
    fn gen_use(
976
76.8k
        &mut self,
977
76.8k
        u: &mut Unstructured<'_>,
978
76.8k
        part: &mut String,
979
76.8k
        world_name: Option<&str>,
980
76.8k
    ) -> Result<bool> {
981
76.8k
        let mut path = String::new();
982
21.3k
        let (_name, _id, types) =
983
76.8k
            match self.generator.gen_interface_path(u, self.file, &mut path)? {
984
21.3k
                Some(types) => types,
985
55.4k
                None => return Ok(false),
986
            };
987
21.3k
        part.push_str("use ");
988
21.3k
        part.push_str(&path);
989
21.3k
        part.push_str(".{");
990
21.3k
        let ty = u.choose(types)?;
991
21.3k
        part.push_str("%");
992
21.3k
        part.push_str(&ty.name);
993
21.3k
        let size = ty.size;
994
21.3k
        let is_resource = ty.is_resource;
995
21.3k
        let name = if self.unique_names.contains(&ty.name) || u.arbitrary()? {
996
20.0k
            part.push_str(" as %");
997
20.0k
            let name = self.gen_unique_name(u)?;
998
20.0k
            part.push_str(&name);
999
            // if we name something then we need track it at the package level for includes
1000
20.0k
            if let Some(world_name) = world_name {
1001
1.10k
                self.generator.packages.add_name(
1002
1.10k
                    self.package_name.to_string(),
1003
1.10k
                    world_name.to_string(),
1004
1.10k
                    name.to_string(),
1005
1.10k
                );
1006
18.9k
            }
1007
20.0k
            name
1008
        } else {
1009
1.33k
            assert!(self.unique_names.insert(ty.name.clone()));
1010
1.33k
            ty.name.clone()
1011
        };
1012
21.3k
        self.types_in_interface.push(Type {
1013
21.3k
            name,
1014
21.3k
            size,
1015
21.3k
            is_resource,
1016
21.3k
        });
1017
21.3k
        part.push_str("};");
1018
21.3k
        Ok(true)
1019
76.8k
    }
1020
1021
21.3k
    fn gen_typedef(
1022
21.3k
        &mut self,
1023
21.3k
        u: &mut Unstructured<'_>,
1024
21.3k
        name: &str,
1025
21.3k
        ret: &mut String,
1026
21.3k
    ) -> Result<Type> {
1027
        #[derive(Arbitrary)]
1028
        pub enum Kind {
1029
            Record,
1030
            Flags,
1031
            Variant,
1032
            Enum,
1033
            Anonymous,
1034
            Resource,
1035
        }
1036
1037
21.3k
        let mut fuel = self.generator.config.max_type_size;
1038
1039
21.3k
        let mut is_resource = false;
1040
21.3k
        match u.arbitrary()? {
1041
            Kind::Record => {
1042
1.78k
                ret.push_str("record %");
1043
1.78k
                ret.push_str(name);
1044
1.78k
                ret.push_str(" {\n");
1045
1.78k
                for _ in 0..u.int_in_range(1..=self.generator.config.max_type_parts)? {
1046
5.51k
                    ret.push_str("  %");
1047
5.51k
                    ret.push_str(&self.gen_unique_name(u)?);
1048
5.51k
                    ret.push_str(": ");
1049
5.51k
                    self.gen_type(u, &mut fuel, 0, ret)?;
1050
5.51k
                    ret.push_str(",\n");
1051
                }
1052
1.78k
                ret.push_str("}");
1053
            }
1054
            Kind::Variant => {
1055
4.86k
                ret.push_str("variant %");
1056
4.86k
                ret.push_str(name);
1057
4.86k
                ret.push_str(" {\n");
1058
4.86k
                for _ in 0..u.int_in_range(1..=self.generator.config.max_type_parts)? {
1059
16.1k
                    ret.push_str("  %");
1060
16.1k
                    ret.push_str(&self.gen_unique_name(u)?);
1061
16.1k
                    if u.arbitrary()? {
1062
14.8k
                        ret.push_str("(");
1063
14.8k
                        self.gen_type(u, &mut fuel, 0, ret)?;
1064
14.8k
                        ret.push_str(")");
1065
1.29k
                    }
1066
16.1k
                    ret.push_str(",\n");
1067
                }
1068
4.86k
                ret.push_str("}");
1069
            }
1070
            Kind::Enum => {
1071
10.1k
                ret.push_str("enum %");
1072
10.1k
                ret.push_str(name);
1073
10.1k
                ret.push_str(" {\n");
1074
10.1k
                for _ in 0..u.int_in_range(1..=self.generator.config.max_type_parts)? {
1075
49.1k
                    ret.push_str("  %");
1076
49.1k
                    ret.push_str(&self.gen_unique_name(u)?);
1077
49.1k
                    ret.push_str(",\n");
1078
                }
1079
10.1k
                ret.push_str("}");
1080
            }
1081
            Kind::Flags => {
1082
979
                ret.push_str("flags %");
1083
979
                ret.push_str(name);
1084
979
                ret.push_str(" {\n");
1085
979
                for _ in 0..u.int_in_range(1..=self.generator.config.max_type_parts)? {
1086
2.62k
                    ret.push_str("  %");
1087
2.62k
                    ret.push_str(&self.gen_unique_name(u)?);
1088
2.62k
                    ret.push_str(",\n");
1089
                }
1090
979
                ret.push_str("}");
1091
            }
1092
            Kind::Anonymous => {
1093
1.95k
                ret.push_str("type %");
1094
1.95k
                ret.push_str(name);
1095
1.95k
                ret.push_str(" = ");
1096
1.95k
                self.gen_type(u, &mut fuel, 0, ret)?;
1097
1.95k
                ret.push_str(";");
1098
            }
1099
1.65k
            Kind::Resource => {
1100
1.65k
                is_resource = true;
1101
1.65k
                ret.push_str("resource %");
1102
1.65k
                ret.push_str(name);
1103
1.65k
            }
1104
        }
1105
1106
21.3k
        Ok(Type {
1107
21.3k
            size: self.generator.config.max_type_size - fuel,
1108
21.3k
            is_resource,
1109
21.3k
            name: name.to_string(),
1110
21.3k
        })
1111
21.3k
    }
1112
1113
333k
    fn gen_type(
1114
333k
        &mut self,
1115
333k
        u: &mut Unstructured<'_>,
1116
333k
        fuel: &mut usize,
1117
333k
        depth: usize,
1118
333k
        dst: &mut String,
1119
333k
    ) -> Result<()> {
1120
        #[derive(Arbitrary)]
1121
        enum Kind {
1122
            Bool,
1123
            U8,
1124
            U16,
1125
            U32,
1126
            U64,
1127
            S8,
1128
            S16,
1129
            S32,
1130
            S64,
1131
            F32,
1132
            F64,
1133
            Char,
1134
            String,
1135
            Id,
1136
            Tuple,
1137
            Option,
1138
            Result,
1139
            List,
1140
            FixedLengthList,
1141
            Stream,
1142
            Future,
1143
            ErrorContext,
1144
        }
1145
1146
        // Bail out with a leaf type if a nested type here would nest too
1147
        // deeply. Note that this is intentionally smaller than wasmparser's
1148
        // current limit of 100 to give some wiggle room to the generator here
1149
        // to be off-by-one.
1150
        const MAX_DEPTH: usize = 50;
1151
333k
        if depth + 1 >= MAX_DEPTH {
1152
13.5k
            dst.push_str("bool");
1153
13.5k
            return Ok(());
1154
319k
        }
1155
1156
319k
        *fuel = match fuel.checked_sub(1) {
1157
280k
            Some(fuel) => fuel,
1158
            None => {
1159
39.4k
                dst.push_str("bool");
1160
39.4k
                return Ok(());
1161
            }
1162
        };
1163
        loop {
1164
303k
            break match u.arbitrary()? {
1165
19.6k
                Kind::Bool => dst.push_str("bool"),
1166
6.84k
                Kind::U8 => dst.push_str("u8"),
1167
6.87k
                Kind::S8 => dst.push_str("s8"),
1168
1.98k
                Kind::U16 => dst.push_str("u16"),
1169
1.84k
                Kind::S16 => dst.push_str("s16"),
1170
2.18k
                Kind::U32 => dst.push_str("u32"),
1171
2.17k
                Kind::S32 => dst.push_str("s32"),
1172
1.95k
                Kind::U64 => dst.push_str("u64"),
1173
8.11k
                Kind::S64 => dst.push_str("s64"),
1174
4.20k
                Kind::F32 => dst.push_str("f32"),
1175
6.21k
                Kind::F64 => dst.push_str("f64"),
1176
14.0k
                Kind::Char => dst.push_str("char"),
1177
1.60k
                Kind::String => dst.push_str("string"),
1178
                Kind::Id => {
1179
4.63k
                    if self.types_in_interface.is_empty() {
1180
2.73k
                        continue;
1181
1.90k
                    }
1182
1.90k
                    let ty = u.choose(&self.types_in_interface)?;
1183
1.90k
                    *fuel = match fuel.checked_sub(ty.size) {
1184
1.84k
                        Some(fuel) => fuel,
1185
57
                        None => continue,
1186
                    };
1187
1.84k
                    let own_wrapper = if ty.is_resource && u.arbitrary()? {
1188
355
                        dst.push_str("own<");
1189
355
                        true
1190
                    } else {
1191
1.48k
                        false
1192
                    };
1193
1.84k
                    dst.push_str("%");
1194
1.84k
                    dst.push_str(&ty.name);
1195
1.84k
                    if own_wrapper {
1196
355
                        dst.push_str(">");
1197
1.48k
                    }
1198
                }
1199
                Kind::Tuple => {
1200
24.1k
                    let fields = u.int_in_range(1..=self.generator.config.max_type_parts)?;
1201
24.1k
                    *fuel = match fuel.checked_sub(fields) {
1202
22.4k
                        Some(fuel) => fuel,
1203
1.67k
                        None => continue,
1204
                    };
1205
22.4k
                    dst.push_str("tuple<");
1206
83.2k
                    for i in 0..fields {
1207
83.2k
                        if i > 0 {
1208
60.7k
                            dst.push_str(", ");
1209
60.7k
                        }
1210
83.2k
                        self.gen_type(u, fuel, depth + 1, dst)?;
1211
                    }
1212
22.4k
                    dst.push_str(">");
1213
                }
1214
                Kind::Option => {
1215
25.4k
                    *fuel = match fuel.checked_sub(1) {
1216
24.9k
                        Some(fuel) => fuel,
1217
519
                        None => continue,
1218
                    };
1219
24.9k
                    dst.push_str("option<");
1220
24.9k
                    self.gen_type(u, fuel, depth + 1, dst)?;
1221
24.9k
                    dst.push_str(">");
1222
                }
1223
                Kind::List => {
1224
4.59k
                    *fuel = match fuel.checked_sub(1) {
1225
4.20k
                        Some(fuel) => fuel,
1226
391
                        None => continue,
1227
                    };
1228
4.20k
                    dst.push_str("list<");
1229
4.20k
                    self.gen_type(u, fuel, depth + 1, dst)?;
1230
4.20k
                    dst.push_str(">");
1231
                }
1232
                Kind::FixedLengthList => {
1233
96.3k
                    if !self.generator.config.fixed_length_lists {
1234
929
                        continue;
1235
95.4k
                    }
1236
95.4k
                    *fuel = match fuel.checked_sub(1) {
1237
95.4k
                        Some(fuel) => fuel,
1238
35
                        None => continue,
1239
                    };
1240
95.4k
                    let elements =
1241
95.4k
                        u.int_in_range(1..=self.generator.config.max_type_parts as u32)?;
1242
95.4k
                    dst.push_str("list<");
1243
95.4k
                    self.gen_type(u, fuel, depth + 1, dst)?;
1244
95.4k
                    dst.push_str(&format!(", {elements}>"));
1245
                }
1246
                Kind::Result => {
1247
13.6k
                    *fuel = match fuel.checked_sub(2) {
1248
13.0k
                        Some(fuel) => fuel,
1249
566
                        None => continue,
1250
                    };
1251
13.0k
                    dst.push_str("result");
1252
13.0k
                    let ok = u.arbitrary()?;
1253
13.0k
                    let err = u.arbitrary()?;
1254
13.0k
                    match (ok, err) {
1255
                        (true, true) => {
1256
9.95k
                            dst.push_str("<");
1257
9.95k
                            self.gen_type(u, fuel, depth + 1, dst)?;
1258
9.95k
                            dst.push_str(", ");
1259
9.95k
                            self.gen_type(u, fuel, depth + 1, dst)?;
1260
9.95k
                            dst.push_str(">");
1261
                        }
1262
                        (true, false) => {
1263
1.83k
                            dst.push_str("<");
1264
1.83k
                            self.gen_type(u, fuel, depth + 1, dst)?;
1265
1.83k
                            dst.push_str(">");
1266
                        }
1267
                        (false, true) => {
1268
1.06k
                            dst.push_str("<_, ");
1269
1.06k
                            self.gen_type(u, fuel, depth + 1, dst)?;
1270
1.06k
                            dst.push_str(">");
1271
                        }
1272
251
                        (false, false) => {}
1273
                    }
1274
                }
1275
                Kind::Stream => {
1276
5.56k
                    if !self.generator.config.streams {
1277
1.68k
                        continue;
1278
3.88k
                    }
1279
3.88k
                    *fuel = match fuel.checked_sub(1) {
1280
3.76k
                        Some(fuel) => fuel,
1281
123
                        None => continue,
1282
                    };
1283
3.76k
                    dst.push_str("stream<");
1284
3.76k
                    self.gen_type(u, fuel, depth + 1, dst)?;
1285
3.76k
                    dst.push_str(">");
1286
                }
1287
                Kind::Future => {
1288
13.5k
                    if !self.generator.config.futures {
1289
1.22k
                        continue;
1290
12.3k
                    }
1291
12.3k
                    *fuel = match fuel.checked_sub(1) {
1292
12.2k
                        Some(fuel) => fuel,
1293
73
                        None => continue,
1294
                    };
1295
12.2k
                    if u.arbitrary()? {
1296
10.7k
                        dst.push_str("future<");
1297
10.7k
                        self.gen_type(u, fuel, depth + 1, dst)?;
1298
10.7k
                        dst.push_str(">");
1299
1.45k
                    } else {
1300
1.45k
                        dst.push_str("future");
1301
1.45k
                    }
1302
                }
1303
                Kind::ErrorContext => {
1304
37.7k
                    if !self.generator.config.error_context {
1305
12.9k
                        continue;
1306
24.8k
                    }
1307
24.8k
                    dst.push_str("error-context");
1308
                }
1309
            };
1310
        }
1311
1312
280k
        Ok(())
1313
333k
    }
1314
1315
13.4k
    fn gen_func(&mut self, u: &mut Unstructured<'_>, ret: &mut String) -> Result<()> {
1316
13.4k
        ret.push_str("%");
1317
13.4k
        ret.push_str(&self.gen_unique_name(u)?);
1318
13.4k
        ret.push_str(": ");
1319
13.4k
        self.gen_func_sig(u, ret, false)?;
1320
13.4k
        Ok(())
1321
13.4k
    }
1322
1323
19.3k
    fn gen_func_sig(
1324
19.3k
        &mut self,
1325
19.3k
        u: &mut Unstructured<'_>,
1326
19.3k
        dst: &mut String,
1327
19.3k
        method: bool,
1328
19.3k
    ) -> Result<()> {
1329
19.3k
        if self.generator.config.async_ && u.arbitrary()? {
1330
12.0k
            dst.push_str("async ");
1331
12.0k
        }
1332
19.3k
        dst.push_str("func");
1333
19.3k
        self.gen_params(u, dst, method)?;
1334
19.3k
        if u.arbitrary()? {
1335
15.3k
            dst.push_str(" -> ");
1336
15.3k
            let mut fuel = self.generator.config.max_type_size;
1337
15.3k
            self.gen_type(u, &mut fuel, 0, dst)?;
1338
3.97k
        }
1339
19.3k
        dst.push_str(";");
1340
19.3k
        Ok(())
1341
19.3k
    }
1342
1343
19.7k
    fn gen_params(
1344
19.7k
        &mut self,
1345
19.7k
        u: &mut Unstructured<'_>,
1346
19.7k
        dst: &mut String,
1347
19.7k
        method: bool,
1348
19.7k
    ) -> Result<()> {
1349
19.7k
        dst.push_str("(");
1350
19.7k
        let mut names = HashSet::new();
1351
19.7k
        if method {
1352
1.92k
            names.insert("self".to_string());
1353
17.8k
        }
1354
19.7k
        let mut fuel = self.generator.config.max_type_size;
1355
50.7k
        for i in 0..u.int_in_range(0..=self.generator.config.max_type_parts)? {
1356
50.7k
            if i > 0 {
1357
34.0k
                dst.push_str(", ");
1358
34.0k
            }
1359
50.7k
            dst.push_str("%");
1360
50.7k
            dst.push_str(&gen_unique_name(u, &mut names)?);
1361
50.7k
            dst.push_str(": ");
1362
50.7k
            self.gen_type(u, &mut fuel, 0, dst)?;
1363
        }
1364
19.7k
        dst.push_str(")");
1365
19.7k
        Ok(())
1366
19.7k
    }
1367
1368
122k
    fn gen_unique_name(&mut self, u: &mut Unstructured<'_>) -> Result<String> {
1369
122k
        gen_unique_name(u, &mut self.unique_names)
1370
122k
    }
1371
}
1372
1373
227k
fn gen_unique_name(u: &mut Unstructured<'_>, set: &mut HashSet<String>) -> Result<String> {
1374
227k
    let mut name = gen_name(u)?;
1375
387k
    while !set.insert(name.clone()) {
1376
160k
        write!(&mut name, "{}", set.len()).unwrap();
1377
160k
    }
1378
227k
    Ok(name)
1379
227k
}
1380
1381
272k
fn gen_name(u: &mut Unstructured<'_>) -> Result<String> {
1382
272k
    let size = u.arbitrary_len::<u8>()?;
1383
272k
    let size = std::cmp::min(size, 20);
1384
272k
    let name = match str::from_utf8(u.peek_bytes(size).unwrap()) {
1385
76.7k
        Ok(s) => {
1386
76.7k
            u.bytes(size).unwrap();
1387
76.7k
            s.to_string()
1388
        }
1389
195k
        Err(e) => {
1390
195k
            let i = e.valid_up_to();
1391
195k
            let valid = u.bytes(i).unwrap();
1392
195k
            str::from_utf8(valid).unwrap().to_string()
1393
        }
1394
    };
1395
272k
    let name = name
1396
272k
        .chars()
1397
982k
        .map(|x| if x.is_ascii_lowercase() { x } else { 'x' })
1398
272k
        .collect::<String>();
1399
272k
    Ok(if name.is_empty() {
1400
188k
        "name".to_string()
1401
    } else {
1402
83.5k
        name
1403
    })
1404
272k
}
1405
1406
70.3k
fn shuffle<T>(u: &mut Unstructured<'_>, mut slice: &mut [T]) -> Result<()> {
1407
222k
    while slice.len() > 0 {
1408
151k
        let pos = u.int_in_range(0..=slice.len() - 1)?;
1409
151k
        slice.swap(0, pos);
1410
151k
        slice = &mut slice[1..];
1411
    }
1412
70.3k
    Ok(())
1413
70.3k
}
wit_smith::generate::shuffle::<wit_smith::generate::File>
Line
Count
Source
1406
7.80k
fn shuffle<T>(u: &mut Unstructured<'_>, mut slice: &mut [T]) -> Result<()> {
1407
26.1k
    while slice.len() > 0 {
1408
18.3k
        let pos = u.int_in_range(0..=slice.len() - 1)?;
1409
18.3k
        slice.swap(0, pos);
1410
18.3k
        slice = &mut slice[1..];
1411
    }
1412
7.80k
    Ok(())
1413
7.80k
}
wit_smith::generate::shuffle::<alloc::string::String>
Line
Count
Source
1406
62.5k
fn shuffle<T>(u: &mut Unstructured<'_>, mut slice: &mut [T]) -> Result<()> {
1407
195k
    while slice.len() > 0 {
1408
133k
        let pos = u.int_in_range(0..=slice.len() - 1)?;
1409
133k
        slice.swap(0, pos);
1410
133k
        slice = &mut slice[1..];
1411
    }
1412
62.5k
    Ok(())
1413
62.5k
}
1414
1415
#[derive(Clone, Default)]
1416
struct File {
1417
    items: Vec<String>,
1418
    namespace: HashMap<String, (DefinitionLevel, DefinitionKind)>,
1419
    interfaces: IndexMap<String, FileInterface>,
1420
    worlds: IndexSet<String>,
1421
}
1422
1423
#[derive(Clone)]
1424
struct FileInterface {
1425
    name: String,
1426
    id: u32,
1427
    types: Rc<Vec<Type>>,
1428
}
1429
1430
#[derive(Debug, Copy, Clone, PartialEq)]
1431
enum DefinitionLevel {
1432
    Package,
1433
    File,
1434
}
1435
1436
#[derive(Debug, Copy, Clone, PartialEq)]
1437
enum DefinitionKind {
1438
    World,
1439
    Interface,
1440
}
1441
1442
enum WorldPath<'a> {
1443
    None,
1444
    Local(&'a str),
1445
    Remote,
1446
}
1447
1448
impl File {
1449
41.5k
    fn gen_unique_package_name(
1450
41.5k
        &mut self,
1451
41.5k
        u: &mut Unstructured<'_>,
1452
41.5k
        names: &mut HashSet<String>,
1453
41.5k
        kind: DefinitionKind,
1454
41.5k
    ) -> Result<String> {
1455
41.5k
        let mut name = gen_name(u)?;
1456
        loop {
1457
            // Find a package-unique name first
1458
69.3k
            if !names.insert(name.clone()) {
1459
27.7k
                write!(&mut name, "{}", names.len()).unwrap();
1460
27.7k
                continue;
1461
41.5k
            }
1462
1463
            // Then make sure it's file-unique too
1464
41.5k
            if self.claim_file_name(&mut name, kind) {
1465
41.5k
                break;
1466
30
            }
1467
        }
1468
41.5k
        Ok(name)
1469
41.5k
    }
1470
1471
3.32k
    fn gen_unique_file_name(
1472
3.32k
        &mut self,
1473
3.32k
        u: &mut Unstructured<'_>,
1474
3.32k
        kind: DefinitionKind,
1475
3.32k
    ) -> Result<String> {
1476
3.32k
        let mut name = gen_name(u)?;
1477
5.04k
        while !self.claim_file_name(&mut name, kind) {
1478
1.71k
            // try again on the next iteration
1479
1.71k
        }
1480
3.32k
        Ok(name)
1481
3.32k
    }
1482
1483
46.6k
    fn claim_file_name(&mut self, name: &mut String, kind: DefinitionKind) -> bool {
1484
46.6k
        match self.namespace.entry(name.clone()) {
1485
2.01k
            Entry::Occupied(mut e) => match e.get().0 {
1486
                // If this name is already claimed elsewhere in the package
1487
                // then that's ok as we're going to shadow it, so switch it
1488
                // to a file definition.
1489
268
                DefinitionLevel::Package => *e.get_mut() = (DefinitionLevel::File, kind),
1490
1491
                // If it's already defined in the file try to add more stuff
1492
                // to the name to make the next try not collide.
1493
                DefinitionLevel::File => {
1494
1.74k
                    name.push_str("y");
1495
1.74k
                    write!(name, "{}", self.namespace.len()).unwrap();
1496
1.74k
                    return false;
1497
                }
1498
            },
1499
1500
            // Not defined? Claim it.
1501
44.6k
            Entry::Vacant(v) => {
1502
44.6k
                v.insert((DefinitionLevel::File, kind));
1503
44.6k
            }
1504
        }
1505
44.8k
        true
1506
46.6k
    }
1507
1508
42.3k
    fn insert_definition(&mut self, name: &str, kind: DefinitionKind) -> bool {
1509
42.3k
        match self.namespace.get(name) {
1510
            // This name is already defined, so it can't be inserted.
1511
19.6k
            Some((DefinitionLevel::File, _)) => return false,
1512
0
            Some(other) => {
1513
0
                panic!("found duplicate definition when should be package-unique: {other:?}")
1514
            }
1515
22.6k
            None => {}
1516
        }
1517
22.6k
        let prev = self
1518
22.6k
            .namespace
1519
22.6k
            .insert(name.to_string(), (DefinitionLevel::Package, kind));
1520
22.6k
        assert!(prev.is_none());
1521
22.6k
        true
1522
42.3k
    }
1523
}
1524
1525
9.38k
fn gen_version_less_than(
1526
9.38k
    u: &mut Unstructured<'_>,
1527
9.38k
    existing_version: &Option<Version>,
1528
9.38k
) -> Result<Version> {
1529
    const MAX_VERSION_RANGE: u64 = 10;
1530
9.38k
    let (major, minor, patch) = match existing_version {
1531
3.42k
        Some(v) => (v.major, v.minor, v.patch),
1532
5.95k
        None => (MAX_VERSION_RANGE, MAX_VERSION_RANGE, MAX_VERSION_RANGE),
1533
    };
1534
1535
9.38k
    let new_version = Version {
1536
9.38k
        major: u.int_in_range(0..=major)?,
1537
9.38k
        minor: u.int_in_range(0..=minor)?,
1538
9.38k
        patch: u.int_in_range(0..=patch)?,
1539
9.38k
        pre: if (u.arbitrary()? && existing_version.is_none())
1540
4.68k
            || existing_version.as_ref().is_some_and(|x| !x.pre.is_empty())
1541
        {
1542
7.40k
            semver::Prerelease::new("alpha.0").unwrap()
1543
        } else {
1544
1.97k
            semver::Prerelease::EMPTY
1545
        },
1546
9.38k
        build: if (u.arbitrary()? && existing_version.is_none())
1547
4.79k
            || existing_version
1548
4.79k
                .as_ref()
1549
4.79k
                .is_some_and(|x| !x.build.is_empty())
1550
        {
1551
7.14k
            semver::BuildMetadata::new("1.2.0").unwrap()
1552
        } else {
1553
2.23k
            semver::BuildMetadata::EMPTY
1554
        },
1555
    };
1556
1557
9.38k
    if let Some(v) = existing_version {
1558
3.42k
        assert!(&new_version <= v, "{} <= {}", &new_version, v);
1559
5.95k
    }
1560
1561
9.38k
    Ok(new_version)
1562
9.38k
}
1563
1564
5.95k
fn gen_version(u: &mut Unstructured<'_>) -> Result<Version> {
1565
5.95k
    gen_version_less_than(u, &None)
1566
5.95k
}