proptest/strategy/
lazy.rs1use crate::std_facade::{fmt, Arc};
11use core::mem;
12
13use crate::strategy::traits::*;
14use crate::test_runner::*;
15
16pub struct LazyValueTree<S: Strategy> {
22 state: LazyValueTreeState<S>,
23}
24
25enum LazyValueTreeState<S: Strategy> {
26 Initialized(S::Tree),
27 Uninitialized {
28 strategy: Arc<S>,
29 runner: TestRunner,
30 },
31 Failed,
32}
33
34impl<S: Strategy> LazyValueTree<S> {
35 pub(crate) fn new(strategy: Arc<S>, runner: &mut TestRunner) -> Self {
38 let runner = runner.partial_clone();
39 Self {
40 state: LazyValueTreeState::Uninitialized { strategy, runner },
41 }
42 }
43
44 pub(crate) fn new_initialized(value_tree: S::Tree) -> Self {
46 Self {
47 state: LazyValueTreeState::Initialized(value_tree),
48 }
49 }
50
51 pub(crate) fn as_inner(&self) -> Option<&S::Tree> {
53 match &self.state {
54 LazyValueTreeState::Initialized(v) => Some(v),
55 LazyValueTreeState::Uninitialized { .. }
56 | LazyValueTreeState::Failed => None,
57 }
58 }
59
60 pub(crate) fn as_inner_mut(&mut self) -> Option<&mut S::Tree> {
62 match &mut self.state {
63 LazyValueTreeState::Initialized(v) => Some(v),
64 LazyValueTreeState::Uninitialized { .. }
65 | LazyValueTreeState::Failed => None,
66 }
67 }
68
69 pub(crate) fn maybe_init(&mut self) {
71 if !self.is_uninitialized() {
72 return;
73 }
74
75 let state = mem::replace(&mut self.state, LazyValueTreeState::Failed);
76 match state {
77 LazyValueTreeState::Uninitialized {
78 strategy,
79 mut runner,
80 } => {
81 match strategy.new_tree(&mut runner) {
82 Ok(v) => {
83 let _ = mem::replace(
84 &mut self.state,
85 LazyValueTreeState::Initialized(v),
86 );
87 }
88 Err(_) => {
89 }
91 }
92 }
93 LazyValueTreeState::Initialized(_) | LazyValueTreeState::Failed => {
94 unreachable!("can only reach here if uninitialized")
95 }
96 }
97 }
98
99 pub(crate) fn is_uninitialized(&self) -> bool {
101 match &self.state {
102 LazyValueTreeState::Uninitialized { .. } => true,
103 LazyValueTreeState::Initialized(_) | LazyValueTreeState::Failed => {
104 false
105 }
106 }
107 }
108
109 pub(crate) fn is_initialized(&self) -> bool {
111 match &self.state {
112 LazyValueTreeState::Initialized(_) => true,
113 LazyValueTreeState::Uninitialized { .. }
114 | LazyValueTreeState::Failed => false,
115 }
116 }
117}
118
119impl<S: Strategy> Clone for LazyValueTree<S>
120where
121 S::Tree: Clone,
122{
123 fn clone(&self) -> Self {
124 Self {
125 state: self.state.clone(),
126 }
127 }
128}
129
130impl<S: Strategy> fmt::Debug for LazyValueTree<S>
131where
132 S::Tree: fmt::Debug,
133{
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 f.debug_struct("LazyValueTree")
136 .field("state", &self.state)
137 .finish()
138 }
139}
140
141impl<S: Strategy> Clone for LazyValueTreeState<S>
142where
143 S::Tree: Clone,
144{
145 fn clone(&self) -> Self {
146 use LazyValueTreeState::*;
147
148 match self {
149 Initialized(v) => Initialized(v.clone()),
150 Uninitialized { strategy, runner } => Uninitialized {
151 strategy: Arc::clone(strategy),
152 runner: runner.clone(),
153 },
154 Failed => Failed,
155 }
156 }
157}
158
159impl<S: Strategy> fmt::Debug for LazyValueTreeState<S>
160where
161 S::Tree: fmt::Debug,
162{
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 match self {
165 LazyValueTreeState::Initialized(value_tree) => {
166 f.debug_tuple("Initialized").field(value_tree).finish()
167 }
168 LazyValueTreeState::Uninitialized { strategy, .. } => f
169 .debug_struct("Uninitialized")
170 .field("strategy", strategy)
171 .finish(),
172 LazyValueTreeState::Failed => write!(f, "Failed"),
173 }
174 }
175}