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
//! This crate allows you to take an arbitrary [`Read`] stream and 'peek ahead'
//! into the stream without consuming the original stream.
//!
//! This is done through the [`PeekRead`] trait which has the method
//! [`peek`]. When this method is called it returns a new [`PeekCursor`] object
//! implementing [`Read`], [`BufRead`] and [`Seek`] that allows you to read from
//! the stream without affecting the original stream.
//!
//! The [`PeekRead`] trait is directly
//! implemented on a select few types, but for most you will have to wrap your
//! type in a [`SeekPeekReader`] or [`BufPeekReader`] that implements the
//! peeking behavior using respectively seeking or buffering.
//!
//! # Examples
//! One could try various different parsers on the same stream until one
//! succeeds:
//! ```no_run
//! # use std::io::{Result, Read, BufRead};
//! # use std::fs::File;
//! # enum ParseResult { Html(()), Jpg(()), Png(()), Gif(()), Js(()), Unknown }
//! # fn parse_as_html<T>(f: T) -> () { () }
//! # fn parse_as_jpg<T>(f: T) -> Result<()> { Ok(()) }
//! # fn parse_as_gif<T>(f: T) -> Result<()> { Ok(()) }
//! # fn parse_as_png<T>(f: T) -> Result<()> { Ok(()) }
//! # fn parse_as_javascript<T>(f: T) -> Result<()> { Ok(()) }
//! # fn foo() -> Result<ParseResult> {
//! # use peekread::{PeekRead, SeekPeekReader};
//! let mut f = SeekPeekReader::new(File::open("ambiguous")?);
//!
//! // HTML is so permissive its parser never fails, so check for signature.
//! if f.starts_with("<!DOCTYPE html>\n") {
//! Ok(ParseResult::Html(parse_as_html(f)))
//! } else {
//! // Can pass PeekCursor to functions accepting T: Read without them
//! // having to be aware of peekread.
//! parse_as_jpg(f.peek()).map(ParseResult::Jpg)
//! .or_else(|_| parse_as_png(f.peek()).map(ParseResult::Png))
//! .or_else(|_| parse_as_gif(f.peek()).map(ParseResult::Gif))
//! .or_else(|_| parse_as_javascript(f.peek()).map(ParseResult::Js))
//! }
//! # }
//! ```
//!
//! [`peek`]: [`PeekRead::peek`]
/// Details for those wishing to implement [`PeekRead`].
pub use BufPeekReader;
pub use PeekCursor;
pub use SeekPeekReader;
use ;
use ;
/// A trait for a [`Read`] stream that supports peeking ahead in the stream.
///
/// In addition to a normal read cursor it can create a separate 'peek cursor'
/// which can go ahead of the regular read cursor, but never behind it. Reading
/// from the peek cursor does not affect the read cursor in any way.