opendal/blocking/write/
std_writer.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::io::Write;
19
20use futures::AsyncWriteExt;
21
22use crate::*;
23
24/// StdWriter is the adapter of [`std::io::Write`] for [`BlockingWriter`].
25///
26/// Users can use this adapter in cases where they need to use [`std::io::Write`] related trait.
27///
28/// # Notes
29///
30/// Files are automatically closed when they go out of scope. Errors detected on closing are ignored
31/// by the implementation of Drop. Use the method `close` if these errors must be manually handled.
32pub struct StdWriter {
33    handle: tokio::runtime::Handle,
34    w: Option<FuturesAsyncWriter>,
35}
36
37impl StdWriter {
38    /// NOTE: don't allow users to create directly.
39    #[inline]
40    pub(crate) fn new(handle: tokio::runtime::Handle, w: Writer) -> Self {
41        StdWriter {
42            handle,
43            w: Some(w.into_futures_async_write()),
44        }
45    }
46
47    /// Close the internal writer and make sure all data have been stored.
48    pub fn close(&mut self) -> std::io::Result<()> {
49        let Some(w) = self.w.as_mut() else {
50            return Err(Error::new(ErrorKind::Unexpected, "writer has been dropped").into());
51        };
52
53        self.handle.block_on(w.close())
54    }
55}
56
57impl Write for StdWriter {
58    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
59        let Some(w) = self.w.as_mut() else {
60            return Err(Error::new(ErrorKind::Unexpected, "writer has been dropped").into());
61        };
62
63        self.handle.block_on(w.write(buf))
64    }
65
66    fn flush(&mut self) -> std::io::Result<()> {
67        let Some(w) = self.w.as_mut() else {
68            return Err(Error::new(ErrorKind::Unexpected, "writer has been dropped").into());
69        };
70
71        self.handle.block_on(w.flush())
72    }
73}
74
75/// Make sure the inner writer is dropped in async context.
76impl Drop for StdWriter {
77    fn drop(&mut self) {
78        if let Some(v) = self.w.take() {
79            self.handle.block_on(async move { drop(v) });
80        }
81    }
82}