proptest/strategy/
just.rs

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
10use crate::std_facade::fmt;
11
12use crate::strategy::{NewTree, Strategy, ValueTree};
13use crate::test_runner::TestRunner;
14
15macro_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"]
34pub struct Just<T: Clone + fmt::Debug>(
35    /// The value produced by this strategy.
36    pub T,
37);
38
39impl<T: Clone + fmt::Debug> Strategy for Just<T> {
40    type Tree = Self;
41    type Value = T;
42
43    fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
44        Ok(self.clone())
45    }
46}
47
48impl<T: Clone + fmt::Debug> ValueTree for Just<T> {
49    type Value = T;
50    noshrink!();
51    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"]
71pub struct LazyJust<T, F: Fn() -> T> {
72    /// The function executed in `.current()`.
73    function: F,
74}
75
76/// Shorthand for `LazyJust<T, fn () -> T>`.
77pub type LazyJustFn<V> = LazyJust<V, fn() -> V>;
78
79impl<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.**
84    pub fn new(function: F) -> Self {
85        Self { function }
86    }
87}
88
89impl<T: fmt::Debug, F: Clone + Fn() -> T> Strategy for LazyJust<T, F> {
90    type Tree = Self;
91    type Value = T;
92
93    fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
94        Ok(self.clone())
95    }
96}
97
98impl<T: fmt::Debug, F: Fn() -> T> ValueTree for LazyJust<T, F> {
99    type Value = T;
100    noshrink!();
101    fn current(&self) -> Self::Value {
102        (self.function)()
103    }
104}
105
106impl<T, F: Copy + Fn() -> T> Copy for LazyJust<T, F> {}
107
108impl<T, F: Clone + Fn() -> T> Clone for LazyJust<T, F> {
109    fn clone(&self) -> Self {
110        Self {
111            function: self.function.clone(),
112        }
113    }
114}
115
116impl<T, F: Fn() -> T> fmt::Debug for LazyJust<T, F> {
117    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
130impl<T: fmt::Debug> Strategy for fn() -> T {
131    type Tree = Self;
132    type Value = T;
133
134    fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
135        Ok(*self)
136    }
137}
138
139impl<T: fmt::Debug> ValueTree for fn() -> T {
140    type Value = T;
141    noshrink!();
142    fn current(&self) -> Self::Value {
143        self()
144    }
145}