1use std::io::Write;
23// this code has been adapted from the `Take` implementation
45/// Writer adapter which limits the bytes written to an underlying writer.
6///
7/// Intended to be a [`std::io::Write`] counterpart to [`std::io::Take`] for [`std::io::Read`]. This
8/// does not force the write limit, for example `give.get_mut()` can be used to write directly to
9/// the underlying writer without updating the internal state of the `Give` object.
10pub struct Give<T> {
11 inner: T,
12 limit: u64,
13}
1415impl<T> Give<T> {
16pub fn new(writer: T, limit: u64) -> Self {
17Self {
18 inner: writer,
19 limit,
20 }
21 }
2223/// Returns the number of bytes that can be written before this instance will return a write of
24 /// 0 bytes.
25pub fn limit(&self) -> u64 {
26self.limit
27 }
2829/// Sets the number of bytes that can be read before this instance will return a write of 0
30 /// bytes. This is the same as constructing a new `Give` instance, so the amount of bytes read
31 /// and the previous limit value don't matter when calling this method.
32pub fn set_limit(&mut self, limit: u64) {
33self.limit = limit;
34 }
3536/// Consumes the `Give`, returning the wrapped writer.
37pub fn into_inner(self) -> T {
38self.inner
39 }
4041/// Gets a reference to the underlying writer.
42pub fn get_ref(&self) -> &T {
43&self.inner
44 }
4546/// Gets a mutable reference to the underlying writer.
47pub fn get_mut(&mut self) -> &mut T {
48&mut self.inner
49 }
50}
5152impl<T: Write> Write for Give<T> {
53fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
54// don't call into the inner writer at all at EOF because it may still block
55if self.limit == 0 {
56return Ok(0);
57 }
5859let max = std::cmp::min(buf.len() as u64, self.limit) as usize;
60let n = self.inner.write(&buf[..max])?;
61self.limit -= n as u64;
62Ok(n)
63 }
6465fn flush(&mut self) -> std::io::Result<()> {
66self.inner.flush()
67 }
68}
6970#[cfg(test)]
71mod tests {
72use super::*;
7374#[test]
75fn test_give_write_1() {
76let mut buf = vec![];
77let mut give = Give::new(&mut buf, 5);
78assert_eq!(give.write(&[0u8; 20]).unwrap(), 5);
79assert_eq!(give.write(&[0u8; 20]).unwrap(), 0);
80assert_eq!(buf.len(), 5);
81 }
8283#[test]
84fn test_give_write_2() {
85let mut buf = vec![];
86let mut give = Give::new(&mut buf, 5);
87assert_eq!(give.write(&[0u8; 3]).unwrap(), 3);
88assert_eq!(give.write(&[0u8; 3]).unwrap(), 2);
89assert_eq!(give.write(&[0u8; 3]).unwrap(), 0);
90assert_eq!(buf.len(), 5);
91 }
9293#[test]
94fn test_give_write_all_1() {
95let mut buf = vec![];
96let mut give = Give::new(&mut buf, 5);
97assert!(give.write_all(&[0u8; 3]).is_ok());
98assert!(give.write_all(&[0u8; 2]).is_ok());
99assert!(give.write_all(&[0u8; 1]).is_err());
100assert_eq!(buf.len(), 5);
101 }
102103#[test]
104fn test_give_write_all_2() {
105let mut buf = vec![];
106let mut give = Give::new(&mut buf, 5);
107assert!(give.write_all(&[0u8; 7]).is_err());
108assert!(give.write_all(&[0u8; 1]).is_err());
109assert!(give.write_all(&[0u8; 7]).is_err());
110assert!(give.write_all(&[0u8; 1]).is_err());
111assert!(give.write_all(&[0u8; 3]).is_err());
112assert_eq!(buf.len(), 5);
113 }
114}