bolero_generator/alloc/
string.rs1use crate::{
2 alloc_generators::{CollectionGenerator, DEFAULT_LEN_RANGE},
3 Driver, TypeGenerator, TypeGeneratorWithParams, TypeValueGenerator, ValueGenerator,
4};
5use alloc::string::String;
6use core::ops::RangeInclusive;
7
8pub struct StringGenerator<C, L> {
9 chars: C,
10 len: L,
11}
12
13impl<C, L> StringGenerator<C, L> {
14 pub fn chars<Gen: ValueGenerator<Output = char>>(self, chars: Gen) -> StringGenerator<Gen, L> {
15 StringGenerator {
16 chars,
17 len: self.len,
18 }
19 }
20
21 pub fn map_chars<Gen: ValueGenerator<Output = char>, F: Fn(C) -> Gen>(
22 self,
23 map: F,
24 ) -> StringGenerator<Gen, L> {
25 StringGenerator {
26 chars: map(self.chars),
27 len: self.len,
28 }
29 }
30
31 pub fn len<Gen: ValueGenerator<Output = usize>>(self, len: Gen) -> StringGenerator<C, Gen> {
32 StringGenerator {
33 chars: self.chars,
34 len,
35 }
36 }
37
38 pub fn map_len<Gen: ValueGenerator<Output = usize>, F: Fn(L) -> Gen>(
39 self,
40 map: F,
41 ) -> StringGenerator<C, Gen> {
42 StringGenerator {
43 chars: self.chars,
44 len: map(self.len),
45 }
46 }
47}
48
49impl<G: ValueGenerator<Output = char>, L: ValueGenerator<Output = usize>> ValueGenerator
50 for StringGenerator<G, L>
51{
52 type Output = String;
53
54 fn generate<D: Driver>(&self, driver: &mut D) -> Option<Self::Output> {
55 let mut value = String::default();
56 self.mutate(driver, &mut value)?;
57 Some(value)
58 }
59
60 fn mutate<D: Driver>(&self, driver: &mut D, value: &mut Self::Output) -> Option<()> {
61 driver.enter_list::<Self::Output, _, _, _>(&self.len, |driver, len| {
62 CollectionGenerator::mutate_collection(value, driver, len, &self.chars)
63 })
64 }
65}
66
67impl CollectionGenerator for String {
68 type Item = char;
69
70 fn mutate_collection<D: Driver, G>(
71 &mut self,
72 driver: &mut D,
73 new_len: usize,
74 item_gen: &G,
75 ) -> Option<()>
76 where
77 G: ValueGenerator<Output = Self::Item>,
78 {
79 let prev = core::mem::take(self);
80
81 let to_mutate = self.len().min(new_len);
82 let to_append = new_len.saturating_sub(to_mutate);
83
84 for mut c in prev.chars().take(to_mutate) {
85 item_gen.mutate(driver, &mut c)?;
86 self.push(c);
87 }
88
89 for _ in 0..to_append {
90 self.push(item_gen.generate(driver)?);
91 }
92
93 #[cfg(test)]
95 assert_eq!(self.chars().count(), new_len);
96
97 Some(())
98 }
99}
100
101impl TypeGenerator for String {
102 fn generate<D: Driver>(driver: &mut D) -> Option<Self> {
103 String::gen_with().generate(driver)
104 }
105}
106
107impl TypeGeneratorWithParams for String {
108 type Output = StringGenerator<TypeValueGenerator<char>, RangeInclusive<usize>>;
109
110 fn gen_with() -> Self::Output {
111 StringGenerator {
112 chars: Default::default(),
113 len: DEFAULT_LEN_RANGE,
114 }
115 }
116}
117
118impl ValueGenerator for String {
119 type Output = Self;
120
121 fn generate<D: Driver>(&self, _driver: &mut D) -> Option<Self> {
122 Some(self.clone())
123 }
124}
125
126#[test]
127fn string_type_test() {
128 let _ = generator_test!(produce::<String>());
129}
130
131#[test]
132fn string_with_test() {
133 let results = generator_test!(produce::<String>().with().len(32usize));
134 assert!(results.into_iter().any(|s| s.chars().count() == 32));
135}