mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-18 00:00:09 +02:00
fs: add CloneFuture for File::try_clone (#850)
This commit is contained in:
committed by
Carl Lerche
parent
3d787b16c7
commit
ab206b976c
@@ -0,0 +1,37 @@
|
||||
use super::File;
|
||||
|
||||
use futures::{Future, Poll};
|
||||
|
||||
use std::io;
|
||||
|
||||
/// Future returned by `File::try_clone`.
|
||||
///
|
||||
/// Clones a file handle into two file handles.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Will panic if polled after returning an item or error.
|
||||
#[derive(Debug)]
|
||||
pub struct CloneFuture {
|
||||
file: Option<File>,
|
||||
}
|
||||
|
||||
impl CloneFuture {
|
||||
pub(crate) fn new(file: File) -> Self {
|
||||
Self { file: Some(file) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for CloneFuture {
|
||||
type Item = (File, File);
|
||||
type Error = (File, io::Error);
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
self.file
|
||||
.as_mut()
|
||||
.expect("Cannot poll `CloneFuture` after it resolves")
|
||||
.poll_try_clone()
|
||||
.map(|inner| inner.map(|cloned| (self.file.take().unwrap(), cloned)))
|
||||
.map_err(|err| (self.file.take().unwrap(), err))
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,14 @@
|
||||
//!
|
||||
//! [`File`]: file/struct.File.html
|
||||
|
||||
mod clone;
|
||||
mod create;
|
||||
mod metadata;
|
||||
mod open;
|
||||
mod open_options;
|
||||
mod seek;
|
||||
|
||||
pub use self::clone::CloneFuture;
|
||||
pub use self::create::CreateFuture;
|
||||
pub use self::metadata::MetadataFuture;
|
||||
pub use self::open::OpenFuture;
|
||||
@@ -407,6 +409,38 @@ impl File {
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a new `File` instance that shares the same underlying file handle
|
||||
/// as the existing `File` instance. Reads, writes, and seeks will affect both
|
||||
/// File instances simultaneously.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```no_run
|
||||
/// # extern crate tokio;
|
||||
/// use tokio::prelude::Future;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let task = tokio::fs::File::create("foo.txt")
|
||||
/// .and_then(|file| {
|
||||
/// file.try_clone()
|
||||
/// .map(|(file, clone)| {
|
||||
/// // do something with the file and the clone
|
||||
/// # println!("{:?} {:?}", file, clone);
|
||||
/// })
|
||||
/// .map_err(|(file, err)| {
|
||||
/// // you get the original file back if there's an error
|
||||
/// # println!("{:?}", file);
|
||||
/// err
|
||||
/// })
|
||||
/// })
|
||||
/// .map_err(|err| eprintln!("IO error: {:?}", err));
|
||||
///
|
||||
/// tokio::run(task);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn try_clone(self) -> CloneFuture {
|
||||
CloneFuture::new(self)
|
||||
}
|
||||
|
||||
/// Changes the permissions on the underlying file.
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
|
||||
@@ -125,3 +125,35 @@ fn seek() {
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone() {
|
||||
let dir = TmpBuilder::new()
|
||||
.prefix("tokio-fs-tests")
|
||||
.tempdir()
|
||||
.unwrap();
|
||||
let file_path = dir.path().join("clone.txt");
|
||||
|
||||
pool::run(
|
||||
File::create(file_path.clone())
|
||||
.and_then(|file| {
|
||||
file.try_clone()
|
||||
.map_err(|(_file, err)| err)
|
||||
.and_then(|(file, clone)| {
|
||||
io::write_all(file, "clone ")
|
||||
.and_then(|_| io::write_all(clone, "successful"))
|
||||
})
|
||||
})
|
||||
.then(|res| {
|
||||
let _ = res.unwrap();
|
||||
Ok(())
|
||||
}),
|
||||
);
|
||||
|
||||
let mut file = StdFile::open(&file_path).unwrap();
|
||||
|
||||
let mut dst = vec![];
|
||||
file.read_to_end(&mut dst).unwrap();
|
||||
|
||||
assert_eq!(dst, b"clone successful")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user