Skip to content

Commit

Permalink
Added docs
Browse files Browse the repository at this point in the history
  • Loading branch information
elichai committed May 1, 2019
1 parent 73311cc commit c10cfc5
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 3 deletions.
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,48 @@
# stdio-override
Overriding Stdio file descriptors in Rust
[![Build Status](https://travis-ci.com/elichai/stdio-override.svg?branch=master)](https://travis-ci.com/elichai/stdio-override)
[![Latest version](https://img.shields.io/crates/v/stdio-override.svg)](https://crates.io/crates/stdio-override)
[![Documentation](https://docs.rs/stdio-override/badge.svg)](https://docs.rs/stdio-override)
![License](https://img.shields.io/crates/l/stdio-override.svg)

A Rust library to easily override Stdio file descriptors in Rust

* [Documentation](https://docs.rs/stdio-override)

## Usage

Add this to your `Cargo.toml`:

```toml
[dependencies]
stdio-override = "0.1"

```

and for Rust Edition 2015 add this to your crate root:

```rust
extern crate stdio_override;
```
In Rust Edition 2018 you can simply do:
```rust
use stdio_override::*;
```

Here's an example on how to write stdout into a file:

```rust
use stdio_override::StdoutOverride;
use std::{fs::read_to_string, mem};

fn main() {
let file_name = "./test.txt";

let guard = StdoutOverride::override_file(file_name).unwrap();
println!("12345");
mem::drop(guard);

let contents = read_to_string(file_name).unwrap();
assert_eq!("12345\n", contents);
println!("Outside!");
}
```
2 changes: 1 addition & 1 deletion src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub use libc::{STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO};
use std::io::{Error, Result};

pub unsafe fn dup(fd: c_int) -> Result<c_int> {
let res = libc::dup(fd) ;
let res = libc::dup(fd);
if res == -1 {
Err(Error::last_os_error())
} else {
Expand Down
34 changes: 33 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

//! # Stdio-Override
//!
//! This crate provides a library for overriding Stdio file descriptors. <br>
//! It provides a Guard for the replacement so that when the guard is dropped the file descriptors are switched back
//! and the replacement File Descriptor will be closed.
//!
//! ** Trying to replace an std File Descriptor twice will result in a panic ** <br>
//!
//! *Notice:* When trying to use this in tests you **must** run with `cargo test -- --nocapture` otherwise it will redirect stdout/stderr again.
//!
//! This library is made to be intuitive and easy to use.
//!
//! ## Examples
//! ```rust
//! use stdio_override::StdoutOverride;
//! use std::{fs, mem};
//! let file_name = "./test.txt";
//! let guard = StdoutOverride::override_file(file_name).unwrap();
//! println!("Isan to Stdout!");
//!
//! let contents = fs::read_to_string(file_name).unwrap();
//! assert_eq!("Isan to Stdout!\n", contents);
//! mem::drop(guard);
//! println!("Outside!");
//! ```
//!
mod ffi;
mod stdout;


pub use stdout::{StdoutOverride, StdoutOverrideGuard};

#[cfg(feature = "test-readme")]
doc_comment::doctest!("../README.md");
16 changes: 16 additions & 0 deletions src/stdout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,23 @@ static IS_REPLACED: AtomicBool = AtomicBool::new(false);

const ORDERING: Ordering = Ordering::SeqCst;

/// A Guard over the Stdout change.
/// when this guard is dropped stdout will go back to the original,
/// and the file will be closed.
pub struct StdoutOverrideGuard {
stdout_fd: RawFd,
file_fd: RawFd,
}

/// Override the Stdout File Descriptor safely.
///
pub struct StdoutOverride;

impl StdoutOverride {
/// Override the stdout by providing a path.
/// This uses [`File::create`] so it will fail/succeed accordingly.
///
/// [`File::create`]: https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.create
pub fn override_file<P: AsRef<Path>>(p: P) -> io::Result<StdoutOverrideGuard> {
Self::check_override();

Expand All @@ -28,6 +37,10 @@ impl StdoutOverride {
Self::override_fd(file_fd)
}

/// Override the stdout by providing something that can be turned into a file descriptor.
/// This will accept Sockets, Files, and even Stdio's. [`AsRawFd`]
///
/// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsRawFd.html
pub fn override_raw<FD: AsRawFd>(fd: FD) -> io::Result<StdoutOverrideGuard> {
Self::check_override();

Expand All @@ -53,8 +66,11 @@ impl StdoutOverride {

impl Drop for StdoutOverrideGuard {
fn drop(&mut self) {
// Ignoring syscalls errors seems to be the most sensible thing to do in a Drop impl
// https://github.com/rust-lang/rust/blob/bd177f3e/src/libstd/sys/unix/fd.rs#L293-L302
let _ = unsafe { dup2(self.stdout_fd, STDOUT_FILENO) };
let _ = unsafe { close(self.file_fd) };
IS_REPLACED.store(false, ORDERING);
}
}

Expand Down

0 comments on commit c10cfc5

Please sign in to comment.