Skip to main content

opendal_core/blocking/read/
std_reader.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;
19use std::io::BufRead;
20use std::io::Read;
21use std::io::Seek;
22use std::io::SeekFrom;
23
24use futures::AsyncBufReadExt;
25use futures::AsyncReadExt;
26use futures::AsyncSeekExt;
27
28use crate::*;
29
30/// `StdReader` adapts a [`crate::blocking::Reader`] to [`Read`], [`Seek`], and
31/// [`BufRead`].
32///
33/// Users can use this adapter in cases where they need to use [`Read`] or [`BufRead`] trait.
34///
35/// StdReader also implements [`Send`] and [`Sync`].
36pub struct StdReader {
37    handle: tokio::runtime::Handle,
38    r: Option<FuturesAsyncReader>,
39}
40
41impl StdReader {
42    /// NOTE: don't allow users to create StdReader directly.
43    #[inline]
44    pub(super) fn new(handle: tokio::runtime::Handle, r: FuturesAsyncReader) -> Self {
45        Self { handle, r: Some(r) }
46    }
47}
48
49impl BufRead for StdReader {
50    fn fill_buf(&mut self) -> io::Result<&[u8]> {
51        let Some(r) = self.r.as_mut() else {
52            return Err(Error::new(ErrorKind::Unexpected, "reader has been dropped").into());
53        };
54
55        self.handle.block_on(r.fill_buf())
56    }
57
58    fn consume(&mut self, amt: usize) {
59        let Some(r) = self.r.as_mut() else {
60            return;
61        };
62
63        r.consume_unpin(amt);
64    }
65}
66
67impl Read for StdReader {
68    #[inline]
69    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
70        let Some(r) = self.r.as_mut() else {
71            return Err(Error::new(ErrorKind::Unexpected, "reader has been dropped").into());
72        };
73
74        self.handle.block_on(r.read(buf))
75    }
76}
77
78impl Seek for StdReader {
79    #[inline]
80    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
81        let Some(r) = self.r.as_mut() else {
82            return Err(Error::new(ErrorKind::Unexpected, "reader has been dropped").into());
83        };
84
85        self.handle.block_on(r.seek(pos))
86    }
87}
88
89/// Make sure the inner reader is dropped in async context.
90impl Drop for StdReader {
91    fn drop(&mut self) {
92        if let Some(v) = self.r.take() {
93            self.handle.block_on(async move { drop(v) });
94        }
95    }
96}