1//! Runtime-agnostic File I/O abstractions.
2//!
3//! Proving only specific API that we need internally.
4
5#[cfg(unix)]
6use std::fs::Metadata;
7use std::{
8 io::Result,
9 path::Path,
10 pin::Pin,
11 task::{Context, Poll},
12};
13
14use futures_core::Stream;
15
16#[cfg(not(feature = "tokio"))]
17#[derive(Debug)]
18pub struct FileLines(futures_util::io::Lines<futures_util::io::BufReader<async_fs::File>>);
19#[cfg(feature = "tokio")]
20#[derive(Debug)]
21pub struct FileLines(tokio::io::Lines<tokio::io::BufReader<tokio::fs::File>>);
22
23impl FileLines {
24 pub async fn open(path: impl AsRef<Path>) -> Result<Self> {
25 #[cfg(not(feature = "tokio"))]
26 {
27 async_fs::File::open(path)
28 .await
29 .map(futures_util::io::BufReader::new)
30 .map(futures_util::AsyncBufReadExt::lines)
31 .map(Self)
32 }
33
34 #[cfg(feature = "tokio")]
35 {
36 tokio::fs::File::open(path)
37 .await
38 .map(tokio::io::BufReader::new)
39 .map(tokio::io::AsyncBufReadExt::lines)
40 .map(Self)
41 }
42 }
43}
44
45impl Stream for FileLines {
46 type Item = Result<String>;
47
48 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
49 #[cfg(not(feature = "tokio"))]
50 {
51 Stream::poll_next(self:Pin::new(&mut self.get_mut().0), cx)
52 }
53
54 #[cfg(feature = "tokio")]
55 {
56 let fut = self.get_mut().0.next_line();
57 futures_util::pin_mut!(fut);
58 std::future::Future::poll(Pin::new(&mut fut), cx).map(Result::transpose)
59 }
60 }
61
62 #[cfg(not(feature = "tokio"))]
63 fn size_hint(&self) -> (usize, Option<usize>) {
64 self.0.size_hint()
65 }
66}
67
68// Not unix-specific itself but only used on unix.
69#[cfg(unix)]
70pub async fn metadata(path: impl AsRef<Path>) -> Result<Metadata> {
71 #[cfg(not(feature = "tokio"))]
72 {
73 async_fs::metadata(path).await
74 }
75
76 #[cfg(feature = "tokio")]
77 {
78 tokio::fs::metadata(path).await
79 }
80}
81