1 //-
2 // Copyright 2017, 2018 The proptest developers
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9 
10 use crate::std_facade::fmt;
11 
12 use crate::strategy::{NewTree, Strategy, ValueTree};
13 use crate::test_runner::TestRunner;
14 
15 macro_rules! noshrink {
16     () => {
17         fn simplify(&mut self) -> bool {
18             false
19         }
20         fn complicate(&mut self) -> bool {
21             false
22         }
23     };
24 }
25 
26 //==============================================================================
27 // Just
28 //==============================================================================
29 
30 /// A `Strategy` which always produces a single value value and never
31 /// simplifies.
32 #[derive(Clone, Copy, Debug)]
33 #[must_use = "strategies do nothing unless used"]
34 pub struct Just<T: Clone + fmt::Debug>(
35     /// The value produced by this strategy.
36     pub T,
37 );
38 
39 impl<T: Clone + fmt::Debug> Strategy for Just<T> {
40     type Tree = Self;
41     type Value = T;
42 
new_tree(&self, _: &mut TestRunner) -> NewTree<Self>43     fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
44         Ok(self.clone())
45     }
46 }
47 
48 impl<T: Clone + fmt::Debug> ValueTree for Just<T> {
49     type Value = T;
50     noshrink!();
current(&self) -> T51     fn current(&self) -> T {
52         self.0.clone()
53     }
54 }
55 
56 //==============================================================================
57 // LazyJust
58 //==============================================================================
59 
60 /// A `Strategy` which always produces a single value value and never
61 /// simplifies. If `T` is `Clone`, you should use `Just` instead.
62 ///
63 /// This is a generalization of `Just` and works by calling
64 /// the provided `Fn () -> T` in `.current()` every time. This is not a
65 /// very interesting strategy, but is required in cases where `T` is
66 /// not `Clone`. It is also used in `proptest_derive` where we can't
67 /// assume that your type is `Clone`.
68 ///
69 /// **It is important that the function used be pure.**
70 #[must_use = "strategies do nothing unless used"]
71 pub struct LazyJust<T, F: Fn() -> T> {
72     /// The function executed in `.current()`.
73     function: F,
74 }
75 
76 /// Shorthand for `LazyJust<T, fn () -> T>`.
77 pub type LazyJustFn<V> = LazyJust<V, fn() -> V>;
78 
79 impl<T, F: Fn() -> T> LazyJust<T, F> {
80     /// Constructs a `LazyJust` strategy given the function/closure
81     /// that produces the value.
82     ///
83     /// **It is important that the function used be pure.**
new(function: F) -> Self84     pub fn new(function: F) -> Self {
85         Self { function }
86     }
87 }
88 
89 impl<T: fmt::Debug, F: Clone + Fn() -> T> Strategy for LazyJust<T, F> {
90     type Tree = Self;
91     type Value = T;
92 
new_tree(&self, _: &mut TestRunner) -> NewTree<Self>93     fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
94         Ok(self.clone())
95     }
96 }
97 
98 impl<T: fmt::Debug, F: Fn() -> T> ValueTree for LazyJust<T, F> {
99     type Value = T;
100     noshrink!();
current(&self) -> Self::Value101     fn current(&self) -> Self::Value {
102         (self.function)()
103     }
104 }
105 
106 impl<T, F: Copy + Fn() -> T> Copy for LazyJust<T, F> {}
107 
108 impl<T, F: Clone + Fn() -> T> Clone for LazyJust<T, F> {
clone(&self) -> Self109     fn clone(&self) -> Self {
110         Self {
111             function: self.function.clone(),
112         }
113     }
114 }
115 
116 impl<T, F: Fn() -> T> fmt::Debug for LazyJust<T, F> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result117     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
118         fmt.debug_struct("LazyJust")
119             .field("function", &"<function>")
120             .finish()
121     }
122 }
123 
124 //==============================================================================
125 // Any `fn () -> T` is a Strategy
126 //==============================================================================
127 
128 // TODO: try 'F: Fn () -> T' instead when we've got specialization.
129 
130 impl<T: fmt::Debug> Strategy for fn() -> T {
131     type Tree = Self;
132     type Value = T;
133 
new_tree(&self, _: &mut TestRunner) -> NewTree<Self>134     fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
135         Ok(*self)
136     }
137 }
138 
139 impl<T: fmt::Debug> ValueTree for fn() -> T {
140     type Value = T;
141     noshrink!();
current(&self) -> Self::Value142     fn current(&self) -> Self::Value {
143         self()
144     }
145 }
146