1# buf\_re(a)dux 2[![Travis](https://img.shields.io/travis/abonander/buf_redux.svg)](https://travis-ci.org/abonander/buf_redux) 3[![Crates.io](https://img.shields.io/crates/v/buf_redux.svg)](https://crates.io/crates/buf_redux) 4[![Crates.io](https://img.shields.io/crates/d/buf_redux.svg)](https://crates.io/crates/buf_redux) 5[![Crates.io](https://img.shields.io/crates/l/buf_redux.svg)](https://crates.io/crates/buf_redux) 6 7Drop-in replacements for buffered I/O types in `std::io`. 8 9These replacements retain the method names/signatures and implemented traits of their stdlib 10counterparts, making replacement as simple as swapping the import of the type. 11 12### More Direct Control 13 14All replacement types provide methods to: 15* Increase the capacity of the buffer 16* Get the number of available bytes as well as the total capacity of the buffer 17* Consume the wrapper without losing data 18 19`BufReader` provides methods to: 20* Access the buffer through an `&`-reference without performing I/O 21* Force unconditional reads into the buffer 22* Get a `Read` adapter which empties the buffer and then pulls from the inner reader directly 23* Shuffle bytes down to the beginning of the buffer to make room for more reading 24* Get inner reader and trimmed buffer with the remaining data 25 26`BufWriter` and `LineWriter` provide methods to: 27* Flush the buffer and unwrap the inner writer unconditionally. 28 29### More Sensible and Customizable Buffering Behavior 30Tune the behavior of the buffer to your specific use-case using the types in the 31`policy` module: 32 33* Refine `BufReader`'s behavior by implementing the `ReaderPolicy` trait or use 34an existing implementation like `MinBuffered` to ensure the buffer always contains 35a minimum number of bytes (until the underlying reader is empty). 36 37* Refine `BufWriter`'s behavior by implementing the `WriterPolicy` trait 38or use an existing implementation like `FlushOn` to flush when a particular byte 39appears in the buffer (used to implement `LineWriter`). 40 41 42## Usage 43 44#### [Documentation](http://docs.rs/buf_redux/) 45 46`Cargo.toml`: 47```toml 48[dependencies] 49buf_redux = "0.2" 50``` 51 52`lib.rs` or `main.rs`: 53```rust 54extern crate buf_redux; 55``` 56 57And then simply swap the import of the types you want to replace: 58 59#### `BufReader`: 60``` 61- use std::io::BufReader; 62+ use buf_redux::BufReader; 63``` 64#### `BufWriter`: 65``` 66- use std::io::BufWriter; 67+ use buf_redux::BufWriter; 68``` 69 70#### `LineWriter`: 71``` 72- use std::io::LineWriter; 73+ use buf_redux::LineWriter; 74``` 75 76### Using `MinBuffered` 77The new `policy::MinBuffered` reader-policy can be used to ensure that `BufReader` always has at least a 78certain number of bytes in its buffer. This can be useful for parsing applications that require a 79certain amount of lookahead. 80 81```rust 82use buf_redux::BufReader; 83use buf_redux::policy::MinBuffered; 84use std::io::{BufRead, Cursor}; 85 86let data = (1 .. 16).collect::<Vec<u8>>(); 87 88// normally you should use `BufReader::new()` or give a capacity of several KiB or more 89let mut reader = BufReader::with_capacity(8, Cursor::new(data)) 90 // always at least 4 bytes in the buffer (or until the source is empty) 91 .set_policy(MinBuffered(4)); // always at least 4 bytes in the buffer 92 93// first buffer fill, same as `std::io::BufReader` 94assert_eq!(reader.fill_buf().unwrap(), &[1, 2, 3, 4, 5, 6, 7, 8]); 95reader.consume(3); 96 97// enough data in the buffer, another read isn't done yet 98assert_eq!(reader.fill_buf().unwrap(), &[4, 5, 6, 7, 8]); 99reader.consume(4); 100 101// `std::io::BufReader` would return `&[8]` 102assert_eq!(reader.fill_buf().unwrap(), &[8, 9, 10, 11, 12, 13, 14, 15]); 103reader.consume(5); 104 105// no data left in the reader 106assert_eq!(reader.fill_buf().unwrap(), &[13, 14, 15]); 107``` 108 109### Note: Making Room / Ringbuffers / `slice-deque` Feature 110With policies like `MinBuffered`, that will read into the buffer and consume bytes from it without completely 111emptying it, normal buffer handling can run out of room to read/write into as all the free space is at the 112head of the buffer. If the amount of data in the buffer is small, you can call `.make_room()` on the buffered 113type to make more room for reading. `MinBuffered` will do this automatically. 114 115Instead of this, with the `slice-deque` feature, you can instead have your buffered type allocate a *ringbuffer*, 116simply by using the `::new_ringbuf()` or `::with_capacity_ringbuf()` constructors instead of 117`::new()` or `with_capacity()`, respectively. With a ringbuffer, consuming/flushing bytes 118from a buffer instantly makes room for more reading/writing at the end. 119However, this has some caveats: 120 121* It is only available on target platforms with virtual memory support, namely fully fledged 122OSes such as Windows and Unix-derivative platforms like Linux, OS X, BSD variants, etc. 123 124* The default capacity varies based on platform, and custom capacities are rounded up to a 125multiple of their minimum size, typically the page size of the platform. 126Windows' minimum size is comparably quite large (**64 KiB**) due to some legacy reasons, 127so this may be less optimal than the default capacity for a normal buffer (8 KiB) for some 128use-cases. 129 130* Due to the nature of the virtual-memory trick, the virtual address space the buffer 131allocates will be double its capacity. This means that your program will *appear* to use more 132memory than it would if it was using a normal buffer of the same capacity. The physical memory 133usage will be the same in both cases, but if address space is at a premium in your application 134(32-bit targets) then this may be a concern. 135 136It is up to you to decide if the benefits outweigh the costs. With a policy like `MinBuffered`, 137it could significantly improve performance. 138 139## License 140 141Licensed under either of 142 143 * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 144 * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 145 146at your option. 147 148### Contribution 149 150Unless you explicitly state otherwise, any contribution intentionally submitted 151for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 152additional terms or conditions. 153