1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
use crate::std_facade::String;
#[cfg(test)]
use crate::std_facade::Vec;
use std::io::ErrorKind::*;
use std::io::*;
use crate::arbitrary::*;
use crate::strategy::statics::static_map;
use crate::strategy::*;
macro_rules! buffer {
    ($type: ident, $bound: path) => {
        arbitrary!(
            [A: Arbitrary + $bound] $type<A>,
            SMapped<(A, Option<u16>), Self>, A::Parameters;
            args => static_map(
                arbitrary_with(product_pack![args, Default::default()]),
                |(inner, cap)| {
                    if let Some(cap) = cap {
                        $type::with_capacity(cap as usize, inner)
                    } else {
                        $type::new(inner)
                    }
                }
            )
        );
        lift1!([$bound] $type<A>; base =>
            (base, any::<Option<u16>>()).prop_map(|(inner, cap)| {
                if let Some(cap) = cap {
                    $type::with_capacity(cap as usize, inner)
                } else {
                    $type::new(inner)
                }
            })
        );
    };
}
buffer!(BufReader, Read);
buffer!(BufWriter, Write);
buffer!(LineWriter, Write);
arbitrary!(
    [A: Read + Arbitrary, B: Read + Arbitrary] Chain<A, B>,
    SMapped<(A, B), Self>, product_type![A::Parameters, B::Parameters];
    args => static_map(arbitrary_with(args), |(a, b)| a.chain(b))
);
wrap_ctor!(Cursor);
lazy_just!(
      Empty, empty
    ; Sink, sink
    ; Stderr, stderr
    ; Stdin, stdin
    ; Stdout, stdout
);
wrap_ctor!([BufRead] Lines, BufRead::lines);
arbitrary!(Repeat, SMapped<u8, Self>; static_map(any::<u8>(), repeat));
arbitrary!(
    [A: BufRead + Arbitrary] Split<A>, SMapped<(A, u8), Self>, A::Parameters;
    args => static_map(
        arbitrary_with(product_pack![args, Default::default()]),
        |(a, b)| a.split(b)
    )
);
lift1!(['static + BufRead] Split<A>;
    base => (base, any::<u8>()).prop_map(|(a, b)| a.split(b)));
arbitrary!(
    [A: Read + Arbitrary] Take<A>, SMapped<(A, u64), Self>, A::Parameters;
    args => static_map(
        arbitrary_with(product_pack![args, Default::default()]),
        |(a, b)| a.take(b)
    )
);
lift1!(['static + Read] Take<A>;
    base => (base, any::<u64>()).prop_map(|(a, b)| a.take(b)));
arbitrary!(ErrorKind, Union<Just<Self>>;
    Union::new(
    [ NotFound
    , PermissionDenied
    , ConnectionRefused
    , ConnectionReset
    , ConnectionAborted
    , NotConnected
    , AddrInUse
    , AddrNotAvailable
    , BrokenPipe
    , AlreadyExists
    , WouldBlock
    , InvalidInput
    , InvalidData
    , TimedOut
    , WriteZero
    , Interrupted
    , Other
    , UnexpectedEof
    
    ].iter().cloned().map(Just))
);
arbitrary!(
    SeekFrom,
    TupleUnion<(
        WA<SMapped<u64, SeekFrom>>,
        WA<SMapped<i64, SeekFrom>>,
        WA<SMapped<i64, SeekFrom>>,
    )>;
    prop_oneof![
        static_map(any::<u64>(), SeekFrom::Start),
        static_map(any::<i64>(), SeekFrom::End),
        static_map(any::<i64>(), SeekFrom::Current)
    ]
);
arbitrary!(Error, SMapped<(ErrorKind, Option<String>), Self>;
    static_map(arbitrary(), |(k, os)|
        if let Some(s) = os { Error::new(k, s) } else { k.into() }
    )
);
#[cfg(test)]
mod test {
    no_panic_test!(
        buf_reader  => BufReader<Repeat>,
        buf_writer  => BufWriter<Sink>,
        line_writer => LineWriter<Sink>,
        chain       => Chain<Empty, BufReader<Repeat>>,
        cursor      => Cursor<Empty>,
        empty       => Empty,
        sink        => Sink,
        stderr      => Stderr,
        stdin       => Stdin,
        stdout      => Stdout,
        lines       => Lines<Empty>,
        repeat      => Repeat,
        split       => Split<Cursor<Vec<u8>>>,
        take        => Take<Repeat>,
        error_kind  => ErrorKind,
        seek_from   => SeekFrom,
        error       => Error
    );
}