generator_combinator/
generator.rs

1#![allow(non_camel_case_types)]
2use crate::iter::StringIter;
3use crate::transformfn::TransformFn;
4use std::{
5    fmt::Display,
6    mem,
7    ops::{Add, AddAssign, BitOr, BitOrAssign, Mul, MulAssign},
8};
9
10/// The building block of generator-combinators.
11///
12/// A `Generator` can be constructed from strings, chars, and slices:
13///
14/// ```
15/// use generator_combinator::Generator;
16/// let foo = Generator::from("foo"); // generates the string `foo`
17/// let dot = Generator::from('.'); // generates the string `.`
18/// let countries = Generator::from(&["US", "FR", "NZ", "CH"][..]); // generates strings `US`, `FR`, `NZ`, and `CH`.
19/// ```
20///
21/// Individual `Generator`s can be combined as sequences with `+`, as variants with `|`, and with repetition with `* usize` and `* (usize, usize)`:
22///
23/// ```
24/// use generator_combinator::Generator;
25/// let foo = Generator::from("foo");
26/// let bar = Generator::from("bar");
27/// let foobar = foo.clone() + bar.clone(); // generates `foobar`
28/// let foo_or_bar = foo.clone() | bar.clone(); // generates `foo`, `bar`
29/// let foo_or_bar_x2 = foo_or_bar.clone() * 2; // generates `foofoo`, `foobar`, `barfoo`, `barbar`
30/// let foo_x2_to_x4 = foo.clone() * (2, 4); // generates `foofoo`, `foofoofoo`, `foofoofoofoo`
31/// ```
32#[derive(Clone, Debug, PartialEq)]
33pub enum Generator {
34    // Some convenience 'constants':
35    /// Lowercase ASCII letters (a-z)
36    AlphaLower,
37
38    /// Uppercase ASCII letters (A-Z)
39    AlphaUpper,
40
41    /// Base-10 digits (0-9)
42    Digit,
43
44    /// Lowercase ASCII letters and digits (a-z0-9)
45    AlphaNumLower,
46
47    /// Uppercase ASCII letters and digits (A-Z0-9)
48    AlphaNumUpper,
49
50    /// Uppercase hexadecimal values (0-9A-F)
51    HexUpper,
52
53    /// Lowercase hexadecimal values (0-9a-f)
54    HexLower,
55
56    /// Generates a [`char`] literal.
57    Char(char),
58
59    /// Generates a [`String`] literal.
60    ///
61    /// Note that this is not a character class.
62    /// `Str("foo".into())` generates the exact string `"foo"`
63    Str(String),
64
65    /// A choice between two or more patterns
66    ///
67    /// As a regex, this would be, eg, `(a|b|c)?` (depending on `is_optional`)
68    OneOf {
69        v: Vec<Generator>,
70        is_optional: bool,
71    },
72
73    /// A pattern repeated exactly _n_ times. This is the same as [`RepeatedMN`](Self::RepeatedMN)`(a, n, n)`
74    ///
75    /// As a regex, this would be `a{n}`
76    RepeatedN(Box<Generator>, usize),
77
78    /// A pattern repeated at least _m_ times, as many as _n_ times.
79    ///
80    /// As a regex, this would be `a{m,n}`
81    RepeatedMN(Box<Generator>, usize, usize),
82
83    /// Two or more sequential patterns.
84    ///
85    /// As a regex, this would be, eg, `abc`
86    Sequence(Vec<Generator>),
87
88    /// Wrap the current generator in a user-defined transformation.
89    Transform {
90        inner: Box<Generator>,
91        transform_fn: TransformFn,
92    },
93
94    /// Doesn't generate anything
95    Empty,
96}
97
98impl Generator {
99    const ASCII_LOWER_A: u8 = 97;
100    const ASCII_UPPER_A: u8 = 65;
101    const ASCII_0: u8 = 48;
102
103    /// Create a regular expression that represents the patterns generated.
104    ///
105    /// The result here is currently best-guess. It's not guaranteed valid, correct, idiomatic, etc.
106    pub fn regex(&self) -> String {
107        use Generator::*;
108
109        match self {
110            AlphaLower => "[a-z]".into(),
111            AlphaUpper => "[A-Z]".into(),
112            Digit => "\\d".into(),
113            AlphaNumUpper => "[A-Z\\d]".into(),
114            AlphaNumLower => "[a-z\\d]".into(),
115            HexUpper => "[\\dA-F]".into(),
116            HexLower => "[\\da-f]".into(),
117            Char(c) => match c {
118                &'.' => "\\.".into(),
119                c => String::from(*c),
120            },
121            Str(s) => s.replace('.', "\\."),
122            OneOf { v, is_optional } => {
123                let regexes = v.iter().map(|a| a.regex()).collect::<Vec<_>>();
124                let mut grp = format!("({})", regexes.join("|"));
125                if *is_optional {
126                    grp.push('?');
127                }
128                grp
129            }
130            RepeatedN(a, n) => a.regex() + "{" + &n.to_string() + "}",
131            RepeatedMN(a, m, n) => a.regex() + "{" + &m.to_string() + "," + &n.to_string() + "}",
132            Sequence(v) => {
133                let regexes = v.iter().map(|a| a.regex()).collect::<Vec<_>>();
134                regexes.join("")
135            }
136            Transform {
137                inner,
138                transform_fn: _,
139            } => inner.regex(),
140            Empty => String::new(),
141        }
142    }
143
144    /// The number of possible patterns represented.
145    pub fn len(&self) -> u128 {
146        use Generator::*;
147        match self {
148            AlphaLower | AlphaUpper => 26,
149            Digit => 10,
150            AlphaNumUpper | AlphaNumLower => 36,
151            HexUpper | HexLower => 16,
152
153            Char(_) | Str(_) => 1,
154
155            OneOf { v, is_optional } => {
156                // Optionals add one value (empty/null)
157                v.iter().map(|a| a.len()).sum::<u128>() + if *is_optional { 1 } else { 0 }
158            }
159
160            // Repeated variants are like base-x numbers of length n, where x is the number of combinations for a.
161            // RepeatedN is easy:
162            RepeatedN(a, n) => a.len().pow(*n as u32),
163            // RepeatedMN has to remove the lower 'bits'/'digits'
164            RepeatedMN(a, m, n) => {
165                let base = a.len();
166                (*m..=*n).map(|i| base.pow(i as u32)).sum()
167            }
168
169            Sequence(v) => v.iter().map(|a| a.len()).product(),
170            Transform {
171                inner,
172                transform_fn: _,
173            } => inner.len(),
174            Empty => 1,
175        }
176    }
177
178    /// Recursively generates the pattern encoded in `num`, appending values to the `result`.
179    fn generate_on_top_of(&self, num: &mut u128, result: &mut String) {
180        use Generator::*;
181
182        match self {
183            AlphaLower => {
184                let i = (*num % 26) as u8;
185                *num /= 26;
186                let c: char = (Self::ASCII_LOWER_A + i).into();
187                result.push(c);
188            }
189            AlphaUpper => {
190                let i = (*num % 26) as u8;
191                *num /= 26;
192                let c: char = (Self::ASCII_UPPER_A + i).into();
193                result.push(c);
194            }
195            Digit => {
196                let i = (*num % 10) as u8;
197                *num /= 10;
198                let c: char = (Self::ASCII_0 + i).into();
199                result.push(c);
200            }
201            AlphaNumUpper => {
202                let i = (*num % 36) as u8;
203                *num /= 36;
204                let c: char = if i < 26 {
205                    Self::ASCII_UPPER_A + i
206                } else {
207                    Self::ASCII_0 + i - 26
208                }
209                .into();
210                result.push(c);
211            }
212            AlphaNumLower => {
213                let i = (*num % 36) as u8;
214                *num /= 36;
215                let c: char = if i < 26 {
216                    Self::ASCII_LOWER_A + i
217                } else {
218                    Self::ASCII_0 + i - 26
219                }
220                .into();
221                result.push(c);
222            }
223            HexUpper => {
224                let i = (*num % 16) as u8;
225                *num /= 16;
226                let c: char = if i < 10 {
227                    Self::ASCII_0 + i
228                } else {
229                    Self::ASCII_UPPER_A + i - 10
230                }
231                .into();
232                result.push(c);
233            }
234            HexLower => {
235                let i = (*num % 16) as u8;
236                *num /= 16;
237                let c: char = if i < 10 {
238                    Self::ASCII_0 + i
239                } else {
240                    Self::ASCII_LOWER_A + i - 10
241                }
242                .into();
243                result.push(c);
244            }
245            Char(c) => {
246                result.push(*c);
247            }
248            Str(s) => {
249                result.push_str(s);
250            }
251            OneOf { v, is_optional } => {
252                let v_len = self.len();
253
254                // Divide out the impact of this OneOf; the remainder can be
255                // used internally and we'll update num for parent recursions.
256                let new_num = *num / v_len;
257                *num %= v_len;
258
259                if *is_optional && *num == 0 {
260                    // use the optional - don't recurse and don't update result
261                } else {
262                    if *is_optional {
263                        *num -= 1;
264                    }
265                    for a in v {
266                        let a_len = a.len() as u128;
267                        if *num < a_len {
268                            a.generate_on_top_of(num, result);
269                            break;
270                        } else {
271                            // subtract out the impact of this OneOf branch
272                            *num -= a_len;
273                        }
274                    }
275                }
276
277                *num = new_num;
278            }
279            RepeatedN(a, n) => {
280                // Repeat this one exactly n times
281                let mut parts = Vec::with_capacity(*n);
282                for _ in 0..*n {
283                    let mut r = String::new();
284                    a.generate_on_top_of(num, &mut r);
285                    parts.push(r);
286                }
287                parts.reverse();
288                result.push_str(&parts.join(""));
289            }
290            RepeatedMN(a, m, n) => {
291                let mut parts = Vec::with_capacity(n - m + 1);
292                for _ in *m..=*n {
293                    let mut r = String::new();
294                    a.generate_on_top_of(num, &mut r);
295                    parts.push(r);
296                }
297                parts.reverse();
298                result.push_str(&parts.join(""));
299            }
300            Sequence(v) => {
301                for a in v {
302                    a.generate_on_top_of(num, result);
303                }
304            }
305            Transform {
306                inner,
307                transform_fn,
308            } => {
309                let mut r = String::new();
310                inner.generate_on_top_of(num, &mut r);
311                let r = (transform_fn.0)(r);
312                result.push_str(&r);
313            }
314            Empty => {}
315        }
316    }
317
318    /// Generates the [`String`] encoded by the specified `num`.
319    ///
320    /// Panics if `num` exceeds the length given by [Generator::len]
321    pub fn generate_one(&self, num: u128) -> String {
322        let range = self.len();
323        assert!(num < range);
324
325        let mut num = num;
326
327        // build up a single string
328        let mut result = String::new();
329        self.generate_on_top_of(&mut num, &mut result);
330        result
331    }
332
333    /// Makes this `Generator` optional.
334    ///
335    /// As a regex, this is the `?` operator.
336    pub fn optional(self) -> Self {
337        use Generator::OneOf;
338        match self {
339            OneOf {
340                v,
341                is_optional: true,
342            } => OneOf {
343                v,
344                is_optional: true,
345            },
346            OneOf {
347                v,
348                is_optional: false,
349            } => OneOf {
350                v,
351                is_optional: true,
352            },
353            _ => OneOf {
354                v: vec![self],
355                is_optional: true,
356            },
357        }
358    }
359
360    /// Provides an iterator across all possible values for this `Generator`.
361    pub fn generate_all(&self) -> StringIter {
362        self.into()
363    }
364
365    /// Includes a user-defined transformation when generating values.
366    pub fn transform(self, f: fn(String) -> String) -> Self {
367        let transform_fn = TransformFn(Box::new(f));
368
369        Self::Transform {
370            inner: Box::new(self),
371            transform_fn,
372        }
373    }
374
375    /// For a value specified by `num`, applies the callback `cb` for each of the component values
376    /// for this Generator.
377    ///
378    /// This may be preferable to [`generate_one`] if you want to see the individual components
379    /// comprising the final string and/or if you want to avoid the memory allocation and freeing
380    /// by creating the values.
381    pub fn visit_one<F>(&self, mut num: u128, mut cb: F)
382    where
383        F: FnMut(String),
384    {
385        let range = self.len();
386        assert!(num < range);
387
388        self.visit_exact_inner(&mut num, &mut cb);
389    }
390
391    /// Internal function to recursively visit each of the components of this Generator.
392    fn visit_exact_inner<F>(&self, num: &mut u128, cb: &mut F)
393    where
394        F: FnMut(String),
395    {
396        use Generator::*;
397
398        match self {
399            AlphaLower => {
400                let i = (*num % 26) as u8;
401                *num /= 26;
402                let c: char = (Self::ASCII_LOWER_A + i).into();
403                cb(String::from(c));
404            }
405            AlphaUpper => {
406                let i = (*num % 26) as u8;
407                *num /= 26;
408                let c: char = (Self::ASCII_UPPER_A + i).into();
409                cb(String::from(c));
410            }
411            Digit => {
412                let i = (*num % 10) as u8;
413                *num /= 10;
414                let c: char = (Self::ASCII_0 + i).into();
415                cb(String::from(c));
416            }
417            AlphaNumUpper => {
418                let i = (*num % 36) as u8;
419                *num /= 36;
420                let c: char = if i < 26 {
421                    Self::ASCII_UPPER_A + i
422                } else {
423                    Self::ASCII_0 + i - 26
424                }
425                .into();
426                cb(String::from(c));
427            }
428            AlphaNumLower => {
429                let i = (*num % 36) as u8;
430                *num /= 36;
431                let c: char = if i < 26 {
432                    Self::ASCII_LOWER_A + i
433                } else {
434                    Self::ASCII_0 + i - 26
435                }
436                .into();
437                cb(String::from(c));
438            }
439            HexUpper => {
440                let i = (*num % 16) as u8;
441                *num /= 16;
442                let c: char = if i < 10 {
443                    Self::ASCII_0 + i
444                } else {
445                    Self::ASCII_UPPER_A + i - 10
446                }
447                .into();
448                cb(String::from(c));
449            }
450            HexLower => {
451                let i = (*num % 16) as u8;
452                *num /= 16;
453                let c: char = if i < 10 {
454                    Self::ASCII_0 + i
455                } else {
456                    Self::ASCII_LOWER_A + i - 10
457                }
458                .into();
459                cb(String::from(c));
460            }
461            Char(c) => cb(String::from(*c)),
462            Str(s) => cb(s.to_string()),
463            OneOf { v, is_optional } => {
464                let v_len = self.len();
465
466                // Divide out the impact of this OneOf; the remainder can be
467                // used internally and we'll update num for parent recursions.
468                let new_num = *num / v_len;
469                *num %= v_len;
470
471                if *is_optional && *num == 0 {
472                    // use the optional - don't recurse and don't update result
473                } else {
474                    if *is_optional {
475                        *num -= 1;
476                    }
477                    for a in v {
478                        let a_len = a.len();
479                        if *num < a_len {
480                            a.visit_exact_inner(num, cb);
481                            break;
482                        } else {
483                            // subtract out the impact of this OneOf branch
484                            *num -= a_len;
485                        }
486                    }
487                }
488
489                *num = new_num;
490            }
491            RepeatedN(a, n) => {
492                // Repeat this one exactly n times
493                let mut parts = Vec::with_capacity(*n);
494                for _ in 0..*n {
495                    let mut r = String::new();
496                    a.generate_on_top_of(num, &mut r);
497                    parts.push(r);
498                }
499
500                parts.into_iter().rev().for_each(cb);
501            }
502            RepeatedMN(a, m, n) => {
503                let mut parts = Vec::with_capacity(n - m + 1);
504                for _ in *m..=*n {
505                    let mut r = String::new();
506                    a.generate_on_top_of(num, &mut r);
507                    parts.push(r);
508                }
509                parts.into_iter().rev().for_each(cb);
510            }
511            Sequence(v) => v.iter().for_each(|a| a.visit_exact_inner(num, cb)),
512            Transform {
513                inner,
514                transform_fn,
515            } => {
516                let mut r = String::new();
517                inner.generate_on_top_of(num, &mut r);
518                let r = (transform_fn.0)(r);
519                cb(r);
520            }
521            // Empty won't invoke the callback
522            Empty => {}
523        }
524    }
525}
526
527impl Default for Generator {
528    fn default() -> Self {
529        Generator::Empty
530    }
531}
532
533impl From<char> for Generator {
534    fn from(c: char) -> Self {
535        Generator::Char(c)
536    }
537}
538
539impl From<&str> for Generator {
540    fn from(s: &str) -> Self {
541        Generator::Str(s.to_string())
542    }
543}
544
545impl From<String> for Generator {
546    fn from(s: String) -> Self {
547        Generator::Str(s)
548    }
549}
550
551impl<T> From<&[T]> for Generator
552where
553    T: AsRef<str> + Display,
554{
555    fn from(values: &[T]) -> Self {
556        // todo: check for & remove empty strings and set is_optional to true
557        let is_optional = false;
558        let v = values
559            .iter()
560            .map(|value| Generator::Str(value.to_string()))
561            .collect();
562        Generator::OneOf { v, is_optional }
563    }
564}
565
566impl BitOr for Generator {
567    type Output = Self;
568
569    fn bitor(self, rhs: Self) -> Self::Output {
570        use Generator::*;
571        match (self, rhs) {
572            (
573                OneOf {
574                    v: mut v1,
575                    is_optional: opt1,
576                },
577                OneOf {
578                    v: v2,
579                    is_optional: opt2,
580                },
581            ) => {
582                v1.extend(v2);
583
584                let is_optional = opt1 || opt2;
585                OneOf { v: v1, is_optional }
586            }
587            (OneOf { mut v, is_optional }, rhs) => {
588                v.push(rhs);
589                OneOf { v, is_optional }
590            }
591            (lhs, OneOf { mut v, is_optional }) => {
592                v.insert(0, lhs);
593                OneOf { v, is_optional }
594            }
595
596            (lhs, rhs) => {
597                let v = vec![lhs, rhs];
598                OneOf {
599                    v,
600                    is_optional: false,
601                }
602            }
603        }
604    }
605}
606
607/// Mul operator for exact repetitions.
608///
609/// The following expressions are equivalent:
610/// ```
611/// use generator_combinator::Generator;
612/// let foostr = Generator::from("foofoo");
613/// let foomul = Generator::from("foo") * 2;
614/// let fooadd = Generator::from("foo") + Generator::from("foo");
615/// ```
616impl Mul<usize> for Generator {
617    type Output = Self;
618
619    fn mul(self, rhs: usize) -> Self::Output {
620        if rhs == 0 {
621            // Multiplying a generator by 0 transforms it to Empty
622            Generator::Empty
623        } else {
624            let lhs = Box::new(self);
625            Generator::RepeatedN(lhs, rhs)
626        }
627    }
628}
629
630impl MulAssign<usize> for Generator {
631    fn mul_assign(&mut self, rhs: usize) {
632        if rhs == 0 {
633            // Multiplying a generator by 0 transforms it to Empty
634            *self = Generator::Empty;
635        } else {
636            let repeat = self.clone() * rhs;
637            *self = repeat;
638        }
639    }
640}
641
642/// Mul operator for repetitions between `m` and `n` (inclusive)
643/// ```
644/// use generator_combinator::Generator;
645/// let foo_two_to_five_times = Generator::from("foo") * (2,5);
646/// ```
647impl Mul<(usize, usize)> for Generator {
648    type Output = Self;
649
650    fn mul(self, rhs: (usize, usize)) -> Self::Output {
651        let (m, n) = rhs;
652        assert!(m <= n);
653
654        let lhs = Box::new(self);
655        if m == 0 {
656            // if the lower bound is zero, then this is an optional pattern
657            Generator::RepeatedMN(lhs, 1, n).optional()
658        } else {
659            Generator::RepeatedMN(lhs, m, n)
660        }
661    }
662}
663
664impl MulAssign<(usize, usize)> for Generator {
665    fn mul_assign(&mut self, rhs: (usize, usize)) {
666        let (m, n) = rhs;
667        assert!(m <= n);
668
669        let lhs = mem::take(self);
670
671        *self = if m == 0 {
672            Generator::RepeatedMN(Box::new(lhs), 1, n).optional()
673        } else {
674            Generator::RepeatedMN(Box::new(lhs), m, n)
675        };
676    }
677}
678
679/// Add operator for exact repetitions.
680///
681/// The following expressions are equivalent:
682/// ```
683/// use generator_combinator::Generator;
684/// let foostr = Generator::from("foofoo");
685/// let foomul = Generator::from("foo") * 2;
686/// let fooadd = Generator::from("foo") + Generator::from("foo");
687/// ```
688impl Add for Generator {
689    type Output = Self;
690
691    fn add(self, rhs: Self) -> Self::Output {
692        use Generator::*;
693        match (self, rhs) {
694            // + Empty is a no-op
695            (s, Generator::Empty) => s,
696            (Sequence(mut v1), Sequence(v2)) => {
697                v1.extend(v2);
698                Sequence(v1)
699            }
700            (Sequence(mut v1), rhs) => {
701                v1.push(rhs);
702                Sequence(v1)
703            }
704            (lhs, Sequence(v2)) => {
705                let mut v = Vec::with_capacity(1 + v2.len());
706                v.push(lhs);
707                v.extend(v2);
708                Sequence(v)
709            }
710
711            (lhs, rhs) => {
712                let v = vec![lhs, rhs];
713                Sequence(v)
714            }
715        }
716    }
717}
718
719impl AddAssign for Generator {
720    fn add_assign(&mut self, rhs: Self) {
721        use Generator::*;
722        match (self, rhs) {
723            // Adding empty doesn't do anything
724            (_, Generator::Empty) => {}
725            (Sequence(v1), Sequence(v2)) => {
726                v1.extend(v2);
727            }
728            (Sequence(v1), rhs) => {
729                v1.push(rhs);
730            }
731            (lhs, Sequence(v2)) => {
732                let mut v = Vec::with_capacity(1 + v2.len());
733                v.push(mem::take(lhs));
734                v.extend(v2);
735                *lhs = Sequence(v);
736            }
737
738            (lhs, rhs) => {
739                let left = mem::take(lhs);
740                let v = vec![left, rhs];
741                *lhs = Sequence(v)
742            }
743        }
744    }
745}
746
747impl BitOrAssign for Generator {
748    fn bitor_assign(&mut self, rhs: Self) {
749        use Generator::*;
750        match (self, rhs) {
751            (
752                OneOf {
753                    v: v1,
754                    is_optional: opt1,
755                },
756                OneOf {
757                    v: v2,
758                    is_optional: opt2,
759                },
760            ) => {
761                v1.extend(v2);
762                if opt2 {
763                    *opt1 = true;
764                }
765            }
766            (OneOf { v, is_optional: _ }, rhs) => {
767                v.push(rhs);
768            }
769            (lhs, OneOf { mut v, is_optional }) => {
770                let left = mem::take(lhs);
771                v.insert(0, left);
772                *lhs = OneOf { v, is_optional };
773            }
774
775            (lhs, rhs) => {
776                let left = mem::take(lhs);
777                let v = vec![left, rhs];
778                *lhs = OneOf {
779                    v,
780                    is_optional: false,
781                };
782            }
783        }
784    }
785}
786
787macro_rules! impl_add_or {
788    ($t: ty) => {
789        impl Add<$t> for Generator {
790            type Output = Generator;
791
792            fn add(self, rhs: $t) -> Self::Output {
793                let rhs: Generator = rhs.into();
794                self + rhs
795            }
796        }
797
798        impl AddAssign<$t> for Generator {
799            fn add_assign(&mut self, rhs: $t) {
800                *self = std::mem::take(self) + rhs;
801            }
802        }
803
804        impl BitOr<$t> for Generator {
805            type Output = Generator;
806
807            fn bitor(self, rhs: $t) -> Self::Output {
808                let rhs: Generator = rhs.into();
809                self | rhs
810            }
811        }
812
813        impl BitOrAssign<$t> for Generator {
814            fn bitor_assign(&mut self, rhs: $t) {
815                *self = std::mem::take(self) | rhs;
816            }
817        }
818    };
819}
820
821impl_add_or!(String);
822impl_add_or!(&str);
823impl_add_or!(char);
824
825#[cfg(test)]
826mod tests {
827    use super::*;
828    use crate::{gen, oneof};
829    #[test]
830    fn combinations_consts() {
831        let eight_alphas = Generator::AlphaLower * 8;
832        assert_eq!(26u128.pow(8), eight_alphas.len());
833
834        // This is the same as above
835        let eight_alphas = Generator::AlphaLower * (8, 8);
836        assert_eq!(26u128.pow(8), eight_alphas.len());
837
838        // This is all combinations of exactly seven or exactly eight alphas:
839        // aaaaaaa, aaaaaab, ..., zzzzzzz, aaaaaaaa, ..., zzzzzzzz
840        let expected = 26u128.pow(7) + 26u128.pow(8);
841        let seven_or_eight_alphas = Generator::AlphaLower * (7, 8);
842        assert_eq!(expected, seven_or_eight_alphas.len());
843    }
844
845    #[test]
846    fn combinations_mn() {
847        /*
848        Given the regex [ab]{2,3}, we can enumerate this easily:
849        aa, ab, ba, bb,
850        aaa, aab, aba, abb, baa, bab, bba, bbb
851        Total combinations is therefore 12
852        */
853
854        let ab23 = (Generator::from("a") | Generator::from("b")) * (2, 3);
855        assert_eq!(12, ab23.len());
856    }
857
858    #[test]
859    fn combinations_str() {
860        let foo = Generator::from("foo");
861        assert_eq!(1, foo.len());
862    }
863
864    #[test]
865    fn combinations_oneof() {
866        let foo = Generator::from("foo");
867        let bar = Generator::from("bar");
868        assert_eq!(1, foo.len());
869        assert_eq!(1, bar.len());
870
871        let foo_bar = foo | bar;
872        assert_eq!(2, foo_bar.len());
873
874        let baz = Generator::from("baz");
875        assert_eq!(1, baz.len());
876        let foo_bar_baz = foo_bar | baz;
877        assert_eq!(3, foo_bar_baz.len());
878    }
879
880    #[test]
881    fn combinations_optional() {
882        let foo = Generator::from("foo");
883        let bar = Generator::from("bar");
884
885        let opt_foo = Generator::OneOf {
886            v: vec![foo.clone()],
887            is_optional: true,
888        };
889        assert_eq!(2, opt_foo.len());
890
891        let opt_foo_bar = Generator::OneOf {
892            v: vec![foo.clone(), bar.clone()],
893            is_optional: true,
894        };
895        assert_eq!(3, opt_foo_bar.len());
896
897        let mut v = opt_foo_bar.generate_all();
898        assert_eq!(Some("".into()), v.next());
899        assert_eq!(Some("foo".into()), v.next());
900        assert_eq!(Some("bar".into()), v.next());
901        assert_eq!(None, v.next());
902    }
903
904    #[test]
905    fn combinations_email() {
906        use Generator::Char;
907        let username = Generator::AlphaLower * (6, 8);
908        let user_combos = 26u128.pow(6) + 26u128.pow(7) + 26u128.pow(8);
909        assert_eq!(username.len(), user_combos);
910
911        let tld = Generator::from("com")
912            | Generator::from("net")
913            | Generator::from("org")
914            | Generator::from("edu")
915            | Generator::from("gov");
916        let tld_combos = 5;
917        assert_eq!(tld.len(), tld_combos);
918
919        let domain = Generator::AlphaLower * (1, 8) + Char('.') + tld;
920        let domain_combos = (1..=8).map(|i| 26u128.pow(i)).sum::<u128>() * tld_combos;
921        assert_eq!(domain.len(), domain_combos);
922
923        let email = username + Char('@') + domain;
924        assert_eq!(email.len(), domain_combos * user_combos);
925    }
926
927    #[test]
928    fn generate_alpha1() {
929        let alphas2 = Generator::AlphaLower * 2;
930        let aa = alphas2.generate_one(0);
931        assert_eq!(aa, "aa");
932
933        let onetwothree = (Generator::Digit * 10).generate_one(123);
934        assert_eq!(onetwothree, "0000000123");
935
936        // Same thing but with postprocessing
937        let onetwothree = (Generator::Digit * 10)
938            .transform(|s| s.trim_start_matches('0').to_string())
939            .generate_one(123);
940        assert_eq!(onetwothree, "123");
941    }
942
943    #[test]
944    fn generate_hex() {
945        let hex = Generator::from("0x") + Generator::HexUpper * 8;
946
947        assert_eq!(4_294_967_296, hex.len());
948
949        assert_eq!(hex.generate_one(3_735_928_559), "0xDEADBEEF");
950        assert_eq!(hex.generate_one(464_375_821), "0x1BADD00D");
951    }
952
953    #[test]
954    fn simplify() {
955        let foo_opt1 = gen!("foo").optional();
956        let foo_opt1 = foo_opt1.optional(); // making an optional optional shouldn't change it
957
958        let foo_opt2 = gen!("foo").optional();
959        assert_eq!(foo_opt1, foo_opt2);
960    }
961
962    #[test]
963    fn equality() {
964        // test the macros
965        let foo1 = Generator::from("foo");
966        let foo2 = gen!("foo");
967        assert_eq!(foo1, foo2);
968
969        let foo2 = oneof!("foo");
970        assert_eq!(foo1, foo2);
971
972        // test BitOrAssign
973        let foobar1 = oneof!("foo", "bar");
974        let mut foobar2 = gen!("foo");
975        foobar2 |= gen!("bar");
976        assert_eq!(foobar1, foobar2);
977
978        // test AddAssign
979        let foobar1 = gen!("foo") + gen!("bar");
980        let mut foobar2 = gen!("foo");
981        foobar2 += gen!("bar");
982        assert_eq!(foobar1, foobar2);
983
984        // test MulAssign<usize>
985        let foo1 = gen!("foo") * 2;
986        let mut foo2 = gen!("foo");
987        foo2 *= 2;
988        assert_eq!(foo1, foo2);
989
990        // test MulAssign<(usize,usize)>
991        let foo1 = gen!("foo") * (2, 3);
992        let mut foo2 = gen!("foo");
993        foo2 *= (2, 3);
994        assert_eq!(foo1, foo2);
995    }
996
997    #[test]
998    fn test_reduce_optionals() {
999        // A naive implementation might treat this as:
1000        // ("foo" | "") | ("bar" | "") | ("baz" | ""), which could incorrectly generate two unnecessary empty strings
1001        let foo = gen!("foo").optional();
1002        let bar = gen!("bar").optional();
1003        let baz = gen!("baz").optional();
1004        let foobarbaz1 = foo | bar | baz;
1005
1006        // The ideal approach is to know that with each of foo, bar, and baz being optional, it's the same as:
1007        let foobarbaz2 = gen!("foo").optional() | oneof!("bar", "baz");
1008
1009        // Which they are, taken care of by BitOr
1010        assert_eq!(foobarbaz1, foobarbaz2);
1011
1012        // And it will generate the four values as expected
1013        let values: Vec<_> = foobarbaz1.generate_all().collect();
1014        assert_eq!(vec!["", "foo", "bar", "baz"], values);
1015
1016        // Note that the optional value is boosted to the front of the line and foo|bar|baz are commoned up
1017        let foobarbaz3 = gen!("foo") | gen!("bar").optional() | gen!("baz");
1018        assert_eq!(foobarbaz1, foobarbaz3);
1019        assert!(
1020            matches!(foobarbaz3, Generator::OneOf { v, is_optional } if v.len() == 3 && is_optional)
1021        );
1022    }
1023
1024    #[test]
1025    fn test_transform() {
1026        let foobarbaz = oneof!("foo", "bar", "baz");
1027
1028        // Trim any leading 'b' from (foo|bar|baz)
1029        let fooaraz = foobarbaz.clone().transform(|s| {
1030            if s.starts_with("b") {
1031                s.trim_start_matches('b').to_string()
1032            } else {
1033                s
1034            }
1035        });
1036
1037        assert_eq!(3, fooaraz.len());
1038        assert_eq!("foo", fooaraz.generate_one(0));
1039        assert_eq!("ar", fooaraz.generate_one(1));
1040        assert_eq!("az", fooaraz.generate_one(2));
1041
1042        // Uppercase (foo|bar|baz)
1043        let foobarbaz_upper = foobarbaz.clone().transform(|s| s.to_uppercase());
1044        assert_eq!(3, foobarbaz_upper.len());
1045        assert_eq!("FOO", foobarbaz_upper.generate_one(0));
1046        assert_eq!("BAR", foobarbaz_upper.generate_one(1));
1047        assert_eq!("BAZ", foobarbaz_upper.generate_one(2));
1048
1049        let ten_digits = Generator::Digit * 10;
1050        let onetwothree = ten_digits.generate_one(123);
1051        assert_eq!(onetwothree, "0000000123");
1052        let onetwothree = ten_digits
1053            .transform(|s| s.trim_start_matches('0').to_string())
1054            .generate_one(123);
1055        assert_eq!(onetwothree, "123");
1056    }
1057
1058    #[test]
1059    fn test_visit() {
1060        let foobarbaz = oneof!("foo", "bar", "baz");
1061        let fbb_nnnn = foobarbaz + Generator::Digit * 4;
1062
1063        let bar1234 = fbb_nnnn.generate_one(3703);
1064        assert_eq!("bar1234", bar1234);
1065
1066        let mut s = String::with_capacity(7);
1067        fbb_nnnn.visit_one(3703, |part| s.push_str(&part));
1068        assert_eq!("bar1234", s);
1069    }
1070
1071    #[test]
1072    fn regex() {
1073        let foobarbaz = oneof!("foo", "bar", "baz");
1074        let fbb_nnnn = foobarbaz + Generator::Digit * 4;
1075        assert_eq!("(foo|bar|baz)\\d{4}", fbb_nnnn.regex());
1076
1077        let hi45 = Generator::from("hi") * (4, 5);
1078        assert_eq!("hi{4,5}", hi45.regex());
1079
1080        let sea = Generator::from("Seattle") + gen!(", WA").optional();
1081        assert_eq!("Seattle(, WA)?", sea.regex());
1082    }
1083
1084    quickcheck! {
1085        /// Check that `generate_one` will produce the same string as would be visited.
1086        fn street_addresses(n: u128) -> bool {
1087            const RANGE : u128 = 809_190_000;
1088
1089            let space = Generator::from(' ');
1090            let number = (Generator::Digit * (3, 5)).transform(|s| s.trim_start_matches('0').to_string());
1091
1092            let directional = space.clone() + oneof!("N", "E", "S", "W", "NE", "SE", "SW", "NW");
1093            let street_names = space.clone() + oneof!("Boren", "Olive", "Spring", "Cherry", "Seneca", "Yesler", "Madison", "James", "Union", "Mercer");
1094            let street_suffixes = space.clone() + oneof!("Rd", "St", "Ave", "Blvd", "Ln", "Dr", "Way", "Ct", "Pl");
1095
1096            let address = number
1097                + directional.clone().optional()
1098                + street_names
1099                + street_suffixes
1100                + directional.clone().optional();
1101
1102            assert_eq!(address.len(), RANGE);
1103            let n = n % RANGE;
1104
1105            let generated = address.generate_one(n);
1106
1107            let mut visited  = String::with_capacity(generated.len());
1108            address.visit_one(n, |part| visited.push_str(&part));
1109            assert_eq!(visited, generated);
1110
1111            true
1112        }
1113    }
1114
1115    #[test]
1116    #[should_panic]
1117    fn exceeds_u128() {
1118        // The range for any generator is store id a `u128`.
1119        // 2**128 == 340282366920938463463374607431768211456, which is 39 digits long.
1120        // Trying to generate a 39 digit string, therefore, exceeds the capacity.
1121        // We can build the generator successfully:
1122        let g = Generator::Digit * 39;
1123
1124        // But when calculating the range, we'll get an overflow:
1125        let _n = g.len();
1126    }
1127
1128    #[test]
1129    fn lower_limit_0() {
1130        // Both should be: empty, a, aa
1131        let g1 = Generator::Char('a') * (0, 2);
1132        let g2 = (Generator::Char('a') * (1, 2)).optional();
1133        assert_eq!(g1.len(), g2.len());
1134        assert_eq!(g1, g2);
1135
1136        let g1 = (Generator::Char('a') * (1, 2)) * 0;
1137        let g2 = Generator::Empty;
1138        assert_eq!(g1.len(), g2.len());
1139        assert_eq!(g1, g2);
1140    }
1141
1142    #[test]
1143    fn oneof_bitorassign_oneof() {
1144        let mut g = oneof!('a', 'b');
1145        g |= oneof!('x', 'y');
1146        assert_eq!(g.len(), 4);
1147    }
1148
1149    #[test]
1150    fn test_add_addassign() {
1151        let g = Generator::from("hello");
1152        let g = g + ',' + ' ' + "world!".to_string();
1153        assert_eq!(g.len(), 1);
1154
1155        let mut g = Generator::from("hello");
1156        g += ',';
1157        g += " world!";
1158
1159        assert_eq!(g.len(), 1);
1160    }
1161
1162    #[test]
1163    fn test_bitor_bitorassign() {
1164        let mut g = Generator::from("hello") | "hi" | "salut".to_string();
1165        g += ", ";
1166        g += Generator::from("world") | "tout le monde" | "everyone";
1167        g += '!';
1168
1169        assert_eq!(g.len(), 9);
1170    }
1171
1172    #[test]
1173    fn test_or_and() {
1174        let mut g = Generator::from("hello");
1175        g |= "salut";
1176        g += ',';
1177        g += " ";
1178        g += Generator::from("world") | "tout le monde" | "🌎";
1179        g += String::from("!");
1180
1181        assert_eq!(g.len(), 6);
1182    }
1183}