opendal/blocking/write/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 super::std_writer::StdWriter;
19use crate::Writer as AsyncWriter;
20use crate::*;
21
22/// BlockingWriter is designed to write data into given path in an blocking
23/// manner.
24pub struct Writer {
25 handle: tokio::runtime::Handle,
26 inner: Option<AsyncWriter>,
27}
28
29impl Writer {
30 /// Create a new writer.
31 ///
32 /// Create will use internal information to decide the most suitable
33 /// implementation for users.
34 ///
35 /// We don't want to expose those details to users so keep this function
36 /// in crate only.
37 pub(crate) fn new(handle: tokio::runtime::Handle, inner: AsyncWriter) -> Self {
38 Self {
39 handle,
40 inner: Some(inner),
41 }
42 }
43
44 /// Write [`Buffer`] into writer.
45 ///
46 /// This operation will write all data in given buffer into writer.
47 ///
48 /// ## Examples
49 ///
50 /// ```
51 /// use bytes::Bytes;
52 /// use opendal::blocking;
53 /// use opendal::blocking::Operator;
54 /// use opendal::Result;
55 ///
56 /// fn test(op: blocking::Operator) -> Result<()> {
57 /// let mut w = op.writer("hello.txt")?;
58 /// // Buffer can be created from continues bytes.
59 /// w.write("hello, world")?;
60 /// // Buffer can also be created from non-continues bytes.
61 /// w.write(vec![Bytes::from("hello,"), Bytes::from("world!")])?;
62 ///
63 /// // Make sure file has been written completely.
64 /// w.close()?;
65 /// Ok(())
66 /// }
67 /// ```
68 pub fn write(&mut self, bs: impl Into<Buffer>) -> Result<()> {
69 let Some(inner) = self.inner.as_mut() else {
70 return Err(Error::new(ErrorKind::Unexpected, "writer has been dropped"));
71 };
72
73 self.handle.block_on(inner.write(bs))
74 }
75
76 /// Close the writer and make sure all data have been committed.
77 ///
78 /// ## Notes
79 ///
80 /// Close should only be called when the writer is not closed or
81 /// aborted, otherwise an unexpected error could be returned.
82 pub fn close(&mut self) -> Result<Metadata> {
83 let Some(inner) = self.inner.as_mut() else {
84 return Err(Error::new(ErrorKind::Unexpected, "writer has been dropped"));
85 };
86
87 self.handle.block_on(inner.close())
88 }
89
90 /// Convert writer into [`StdWriter`] which implements [`std::io::Write`],
91 pub fn into_std_write(mut self) -> StdWriter {
92 let inner = self
93 .inner
94 .take()
95 .ok_or_else(|| Error::new(ErrorKind::Unexpected, "writer has been dropped"))
96 .expect("writer has been dropped");
97
98 StdWriter::new(self.handle.clone(), inner)
99 }
100}
101
102/// Make sure the inner writer is dropped in async context.
103impl Drop for Writer {
104 fn drop(&mut self) {
105 if let Some(v) = self.inner.take() {
106 self.handle.block_on(async move { drop(v) });
107 }
108 }
109}