zenoh_protocol_core/key_expr/
fuzzer.rs

1//
2// Copyright (c) 2022 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12//   ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13//
14use super::OwnedKeyExpr;
15
16fn random_chunk(rng: &'_ mut impl rand::Rng) -> impl Iterator<Item = u8> + '_ {
17    let n = rng.gen_range(1..3);
18    (0..n).map(move |_| rng.sample(rand::distributions::Uniform::from(b'a'..b'c')))
19}
20fn make(ke: &mut Vec<u8>, rng: &mut impl rand::Rng) {
21    let mut iters = 0;
22    loop {
23        let n = rng.sample(rand::distributions::Uniform::<u8>::from(0..=255));
24        match n {
25            0..=15 => ke.extend(b"/**"),
26            16..=31 => ke.extend(b"/*"),
27            32..=47 => {
28                if !ke.is_empty() && !ke.ends_with(b"*") {
29                    ke.extend(b"$*")
30                } else {
31                    continue;
32                }
33            }
34            48.. => {
35                if n >= 128 || ke.ends_with(b"**") || ke.ends_with(b"/*") {
36                    ke.push(b'/')
37                }
38                ke.extend(random_chunk(rng))
39            }
40        }
41        if n % (10 - iters) == 0 {
42            return;
43        }
44        iters += 1;
45    }
46}
47
48pub struct KeyExprFuzzer<Rng: rand::Rng>(pub Rng);
49impl<Rng: rand::Rng> Iterator for KeyExprFuzzer<Rng> {
50    type Item = OwnedKeyExpr;
51    fn next(&mut self) -> Option<Self::Item> {
52        let mut next = Vec::new();
53        make(&mut next, &mut self.0);
54        let mut next = String::from_utf8(next).unwrap();
55        if let Some(n) = next.strip_prefix('/') {
56            next = n.to_owned()
57        }
58        Some(OwnedKeyExpr::autocanonize(next).unwrap())
59    }
60}