libflate/finish.rs
1//! `Finish` and related types.
2
3use core::ops::{Deref, DerefMut};
4use no_std_io2::io::{self, Write};
5
6/// `Finish` is a type that represents a value which
7/// may have an error occurred during the computation.
8///
9/// Logically, `Finish<T, E>` is equivalent to `Result<T, (T, E)>`.
10#[derive(Debug, Default, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
11pub struct Finish<T, E> {
12 value: T,
13 error: Option<E>,
14}
15impl<T, E> Finish<T, E> {
16 /// Makes a new instance.
17 ///
18 /// # Examples
19 /// ```
20 /// use libflate::Finish;
21 ///
22 /// // The result value of a succeeded computation
23 /// let succeeded = Finish::new("value", None as Option<()>);
24 /// assert_eq!(succeeded.into_result(), Ok("value"));
25 ///
26 /// // The result value of a failed computation
27 /// let failed = Finish::new("value", Some("error"));
28 /// assert_eq!(failed.into_result(), Err("error"));
29 /// ```
30 pub fn new(value: T, error: Option<E>) -> Self {
31 Finish { value, error }
32 }
33
34 /// Unwraps the instance.
35 ///
36 /// # Examples
37 /// ```
38 /// use libflate::Finish;
39 ///
40 /// let succeeded = Finish::new("value", None as Option<()>);
41 /// assert_eq!(succeeded.unwrap(), ("value", None));
42 ///
43 /// let failed = Finish::new("value", Some("error"));
44 /// assert_eq!(failed.unwrap(), ("value", Some("error")));
45 /// ```
46 pub fn unwrap(self) -> (T, Option<E>) {
47 (self.value, self.error)
48 }
49
50 /// Converts from `Finish<T, E>` to `Result<T, E>`.
51 ///
52 /// # Examples
53 /// ```
54 /// use libflate::Finish;
55 ///
56 /// let succeeded = Finish::new("value", None as Option<()>);
57 /// assert_eq!(succeeded.into_result(), Ok("value"));
58 ///
59 /// let failed = Finish::new("value", Some("error"));
60 /// assert_eq!(failed.into_result(), Err("error"));
61 /// ```
62 pub fn into_result(self) -> Result<T, E> {
63 if let Some(e) = self.error {
64 Err(e)
65 } else {
66 Ok(self.value)
67 }
68 }
69
70 /// Converts from `Finish<T, E>` to `Result<&T, &E>`.
71 ///
72 /// # Examples
73 /// ```
74 /// use libflate::Finish;
75 ///
76 /// let succeeded = Finish::new("value", None as Option<()>);
77 /// assert_eq!(succeeded.as_result(), Ok(&"value"));
78 ///
79 /// let failed = Finish::new("value", Some("error"));
80 /// assert_eq!(failed.as_result(), Err(&"error"));
81 /// ```
82 pub fn as_result(&self) -> Result<&T, &E> {
83 if let Some(ref e) = self.error {
84 Err(e)
85 } else {
86 Ok(&self.value)
87 }
88 }
89}
90
91/// A wrapper struct that completes the processing of the underlying instance when drops.
92///
93/// This calls `Complete:::complete` method of `T` when drops.
94///
95/// # Panics
96///
97/// If the invocation of `Complete::complete(T)` returns an error, `AutoFinish::drop()` will panic.
98#[derive(Debug)]
99pub struct AutoFinish<T: Complete> {
100 inner: Option<T>,
101}
102impl<T: Complete> AutoFinish<T> {
103 /// Makes a new `AutoFinish` instance.
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// use no_std_io2::io::Write;
109 /// use libflate::finish::AutoFinish;
110 /// use libflate::gzip::Encoder;
111 ///
112 /// let plain = b"Hello World!";
113 /// let mut buf = Vec::new();
114 /// let mut encoder = AutoFinish::new(Encoder::new(&mut buf).unwrap());
115 /// encoder.write_all(plain.as_ref()).unwrap();
116 /// ```
117 pub fn new(inner: T) -> Self {
118 AutoFinish { inner: Some(inner) }
119 }
120
121 /// Unwraps this `AutoFinish` instance, returning the underlying instance.
122 pub fn into_inner(mut self) -> T {
123 self.inner.take().expect("Never fails")
124 }
125}
126impl<T: Complete> Drop for AutoFinish<T> {
127 fn drop(&mut self) {
128 if let Some(inner) = self.inner.take()
129 && let Err(e) = inner.complete()
130 {
131 panic!("{}", e);
132 }
133 }
134}
135impl<T: Complete> Deref for AutoFinish<T> {
136 type Target = T;
137 fn deref(&self) -> &Self::Target {
138 self.inner.as_ref().expect("Never fails")
139 }
140}
141impl<T: Complete> DerefMut for AutoFinish<T> {
142 fn deref_mut(&mut self) -> &mut Self::Target {
143 self.inner.as_mut().expect("Never fails")
144 }
145}
146impl<T: Complete + Write> Write for AutoFinish<T> {
147 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
148 self.deref_mut().write(buf)
149 }
150 fn flush(&mut self) -> io::Result<()> {
151 self.deref_mut().flush()
152 }
153}
154
155/// A wrapper struct that completes the processing of the underlying instance when drops.
156///
157/// This calls `Complete:::complete` method of `T` when drops.
158///
159/// Note that this ignores the result of the invocation of `Complete::complete(T)`.
160#[derive(Debug)]
161pub struct AutoFinishUnchecked<T: Complete> {
162 inner: Option<T>,
163}
164impl<T: Complete> AutoFinishUnchecked<T> {
165 /// Makes a new `AutoFinishUnchecked` instance.
166 ///
167 /// # Examples
168 ///
169 /// ```
170 /// use no_std_io2::io::Write;
171 /// use libflate::finish::AutoFinishUnchecked;
172 /// use libflate::gzip::Encoder;
173 ///
174 /// let plain = b"Hello World!";
175 /// let mut buf = Vec::new();
176 /// let mut encoder = AutoFinishUnchecked::new(Encoder::new(&mut buf).unwrap());
177 /// encoder.write_all(plain.as_ref()).unwrap();
178 /// ```
179 pub fn new(inner: T) -> Self {
180 AutoFinishUnchecked { inner: Some(inner) }
181 }
182
183 /// Unwraps this `AutoFinishUnchecked` instance, returning the underlying instance.
184 pub fn into_inner(mut self) -> T {
185 self.inner.take().expect("Never fails")
186 }
187}
188impl<T: Complete> Drop for AutoFinishUnchecked<T> {
189 fn drop(&mut self) {
190 if let Some(inner) = self.inner.take() {
191 let _ = inner.complete();
192 }
193 }
194}
195impl<T: Complete> Deref for AutoFinishUnchecked<T> {
196 type Target = T;
197 fn deref(&self) -> &Self::Target {
198 self.inner.as_ref().expect("Never fails")
199 }
200}
201impl<T: Complete> DerefMut for AutoFinishUnchecked<T> {
202 fn deref_mut(&mut self) -> &mut Self::Target {
203 self.inner.as_mut().expect("Never fails")
204 }
205}
206impl<T: Complete + Write> Write for AutoFinishUnchecked<T> {
207 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
208 self.deref_mut().write(buf)
209 }
210 fn flush(&mut self) -> io::Result<()> {
211 self.deref_mut().flush()
212 }
213}
214
215/// This trait allows to complete an I/O related processing.
216pub trait Complete {
217 /// Completes the current processing and returns the result.
218 fn complete(self) -> io::Result<()>;
219}