diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index b07733d3c803c..f40aed2478a17 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -211,6 +211,115 @@ pub struct DirBuilder { recursive: bool, } +/// Read the entire contents of a file into a bytes vector. +/// +/// This is a convenience function for using [`File::open`] and [`read_to_end`] +/// with fewer imports and without an intermediate variable. +/// +/// [`File::open`]: struct.File.html#method.open +/// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end +/// +/// # Errors +/// +/// This function will return an error if `path` does not already exist. +/// Other errors may also be returned according to [`OpenOptions::open`]. +/// +/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open +/// +/// It will also return an error if it encounters while reading an error +/// of a kind other than [`ErrorKind::Interrupted`]. +/// +/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted +/// +/// # Examples +/// +/// ```no_run +/// #![feature(fs_read_write)] +/// +/// use std::fs; +/// use std::net::SocketAddr; +/// +/// # fn foo() -> Result<(), Box> { +/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; +/// # Ok(()) +/// # } +/// ``` +#[unstable(feature = "fs_read_write", issue = "46588")] +pub fn read>(path: P) -> io::Result> { + let mut bytes = Vec::new(); + File::open(path)?.read_to_end(&mut bytes)?; + Ok(bytes) +} + +/// Read the entire contents of a file into a string. +/// +/// This is a convenience function for using [`File::open`] and [`read_to_string`] +/// with fewer imports and without an intermediate variable. +/// +/// [`File::open`]: struct.File.html#method.open +/// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string +/// +/// # Errors +/// +/// This function will return an error if `path` does not already exist. +/// Other errors may also be returned according to [`OpenOptions::open`]. +/// +/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open +/// +/// It will also return an error if it encounters while reading an error +/// of a kind other than [`ErrorKind::Interrupted`], +/// or if the contents of the file are not valid UTF-8. +/// +/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted +/// +/// # Examples +/// +/// ```no_run +/// #![feature(fs_read_write)] +/// +/// use std::fs; +/// use std::net::SocketAddr; +/// +/// # fn foo() -> Result<(), Box> { +/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?; +/// # Ok(()) +/// # } +/// ``` +#[unstable(feature = "fs_read_write", issue = "46588")] +pub fn read_string>(path: P) -> io::Result { + let mut string = String::new(); + File::open(path)?.read_to_string(&mut string)?; + Ok(string) +} + +/// Write a slice as the entire contents of a file. +/// +/// This function will create a file if it does not exist, +/// and will entirely replace its contents if it does. +/// +/// This is a convenience function for using [`File::create`] and [`write_all`] +/// with fewer imports. +/// +/// [`File::create`]: struct.File.html#method.create +/// [`write_all`]: ../io/trait.Write.html#method.write_all +/// +/// # Examples +/// +/// ```no_run +/// #![feature(fs_read_write)] +/// +/// use std::fs; +/// +/// # fn foo() -> std::io::Result<()> { +/// fs::write("foo.txt", b"Lorem ipsum")?; +/// # Ok(()) +/// # } +/// ``` +#[unstable(feature = "fs_read_write", issue = "46588")] +pub fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { + File::create(path)?.write_all(contents.as_ref()) +} + impl File { /// Attempts to open a file in read-only mode. /// @@ -1912,7 +2021,9 @@ mod tests { ) } #[cfg(unix)] - macro_rules! error { ($e:expr, $s:expr) => ( + macro_rules! error { ($e:expr, $s:expr) => ( error_contains!($e, $s) ) } + + macro_rules! error_contains { ($e:expr, $s:expr) => ( match $e { Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), Err(ref err) => assert!(err.to_string().contains($s), @@ -2921,6 +3032,27 @@ mod tests { assert!(v == &bytes[..]); } + #[test] + fn write_then_read() { + let mut bytes = [0; 1024]; + StdRng::new().unwrap().fill_bytes(&mut bytes); + + let tmpdir = tmpdir(); + + check!(fs::write(&tmpdir.join("test"), &bytes[..])); + let v = check!(fs::read(&tmpdir.join("test"))); + assert!(v == &bytes[..]); + + check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF])); + error_contains!(fs::read_string(&tmpdir.join("not-utf8")), + "stream did not contain valid UTF-8"); + + let s = "𐁁𐀓𐀠𐀴𐀍"; + check!(fs::write(&tmpdir.join("utf8"), s.as_bytes())); + let string = check!(fs::read_string(&tmpdir.join("utf8"))); + assert_eq!(string, s); + } + #[test] fn file_try_clone() { let tmpdir = tmpdir(); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 429153dc58b4c..4bc81efe4777e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -269,6 +269,7 @@ #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(fs_read_write)] #![feature(fixed_size_array)] #![feature(float_from_str_radix)] #![feature(fn_traits)]