1use std::{
8 cmp, fmt,
9 io::{self, Read, Write},
10};
11
12use crate::{make_ops, PartialOp};
13
14pub struct PartialRead<R> {
34 inner: R,
35 ops: Box<dyn Iterator<Item = PartialOp> + Send>,
36}
37
38impl<R> PartialRead<R>
39where
40 R: Read,
41{
42 pub fn new<I>(inner: R, iter: I) -> Self
44 where
45 I: IntoIterator<Item = PartialOp> + 'static,
46 I::IntoIter: Send,
47 {
48 PartialRead {
49 inner,
50 ops: make_ops(iter),
51 }
52 }
53
54 pub fn set_ops<I>(&mut self, iter: I) -> &mut Self
56 where
57 I: IntoIterator<Item = PartialOp> + 'static,
58 I::IntoIter: Send,
59 {
60 self.ops = make_ops(iter);
61 self
62 }
63
64 pub fn get_ref(&self) -> &R {
66 &self.inner
67 }
68
69 pub fn get_mut(&mut self) -> &mut R {
71 &mut self.inner
72 }
73
74 pub fn into_inner(self) -> R {
76 self.inner
77 }
78}
79
80impl<R> Read for PartialRead<R>
81where
82 R: Read,
83{
84 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
85 match self.ops.next() {
86 Some(PartialOp::Limited(n)) => {
87 let len = cmp::min(n, buf.len());
88 self.inner.read(&mut buf[..len])
89 }
90 Some(PartialOp::Err(err)) => Err(io::Error::new(
91 err,
92 "error during read, generated by partial-io",
93 )),
94 Some(PartialOp::Unlimited) | None => self.inner.read(buf),
95 }
96 }
97}
98
99impl<R> Write for PartialRead<R>
101where
102 R: Read + Write,
103{
104 #[inline]
105 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
106 self.inner.write(buf)
107 }
108
109 #[inline]
110 fn flush(&mut self) -> io::Result<()> {
111 self.inner.flush()
112 }
113}
114
115impl<R> fmt::Debug for PartialRead<R>
116where
117 R: fmt::Debug,
118{
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 f.debug_struct("PartialRead")
121 .field("inner", &self.inner)
122 .finish()
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 use std::fs::File;
131
132 use crate::tests::assert_send;
133
134 #[test]
135 fn test_sendable() {
136 assert_send::<PartialRead<File>>();
137 }
138}