add documentation
This commit is contained in:
parent
88b478e85f
commit
1c411e1cc1
101
src/lib.rs
101
src/lib.rs
|
@ -1,16 +1,74 @@
|
||||||
|
//! Circular, a stream abstraction designed for use with nom
|
||||||
|
//!
|
||||||
|
//! Circular provides a `Buffer` type that wraps a `Vec<u8>` with a position
|
||||||
|
//! and end. Compared to a stream abstraction that would use `std::io::Read`,
|
||||||
|
//! it separates the reading and consuming phases. `Read` is designed to write
|
||||||
|
//! the data in a mutable slice and consume it from the stream as it does that.
|
||||||
|
//!
|
||||||
|
//! When used in streaming mode, nom will try to parse a slice, then tell you
|
||||||
|
//! how much it consumed. So you don't know how much data was actually used
|
||||||
|
//! until the parser returns. `Circular::Buffer` exposes a `data()` method
|
||||||
|
//! that gives an immutable slice of all the currently readable data,
|
||||||
|
//! and a `consume()` method to advance the position in the stream.
|
||||||
|
//! The `space()` and `fill()` methods are the write counterparts to those methods.
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! extern crate circular;
|
||||||
|
//!
|
||||||
|
//! use circular::Buffer;
|
||||||
|
//! use std::io::Write;
|
||||||
|
//!
|
||||||
|
//! fn main() {
|
||||||
|
//!
|
||||||
|
//! // allocate a new Buffer
|
||||||
|
//! let mut b = Buffer::with_capacity(10);
|
||||||
|
//! assert_eq!(b.available_data(), 0);
|
||||||
|
//! assert_eq!(b.available_space(), 10);
|
||||||
|
//!
|
||||||
|
//! let res = b.write(&b"abcd"[..]);
|
||||||
|
//! assert_eq!(res.ok(), Some(4));
|
||||||
|
//! assert_eq!(b.available_data(), 4);
|
||||||
|
//! assert_eq!(b.available_space(), 6);
|
||||||
|
//!
|
||||||
|
//! //the 4 bytes we wrote are immediately available and usable for parsing
|
||||||
|
//! assert_eq!(b.data(), &b"abcd"[..]);
|
||||||
|
//!
|
||||||
|
//! // this will advance the position from 0 to 2. it does not modify the underlying Vec
|
||||||
|
//! b.consume(2);
|
||||||
|
//! assert_eq!(b.available_data(), 2);
|
||||||
|
//! assert_eq!(b.available_space(), 6);
|
||||||
|
//! assert_eq!(b.data(), &b"cd"[..]);
|
||||||
|
//!
|
||||||
|
//! // shift moves the available data at the beginning of the buffer.
|
||||||
|
//! // the position is now 0
|
||||||
|
//! b.shift();
|
||||||
|
//! assert_eq!(b.available_data(), 2);
|
||||||
|
//! assert_eq!(b.available_space(), 8);
|
||||||
|
//! assert_eq!(b.data(), &b"cd"[..]);
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
use std::{cmp, ptr};
|
use std::{cmp, ptr};
|
||||||
use std::io::{self,Write,Read};
|
use std::io::{self,Write,Read};
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
|
|
||||||
|
/// the Buffer contains the underlying memory and data positions
|
||||||
|
///
|
||||||
|
/// In all cases, `0 ≤ position ≤ end ≤ capacity` should be true
|
||||||
#[derive(Debug,PartialEq,Clone)]
|
#[derive(Debug,PartialEq,Clone)]
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
|
/// the Vec containing the data
|
||||||
memory: Vec<u8>,
|
memory: Vec<u8>,
|
||||||
|
/// the current capacity of the Buffer
|
||||||
capacity: usize,
|
capacity: usize,
|
||||||
|
/// the current beginning of the available data
|
||||||
position: usize,
|
position: usize,
|
||||||
|
/// the current end of the available data
|
||||||
|
/// and beginning of the available space
|
||||||
end: usize
|
end: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
|
/// allocates a new buffer of maximum size `capacity`
|
||||||
pub fn with_capacity(capacity: usize) -> Buffer {
|
pub fn with_capacity(capacity: usize) -> Buffer {
|
||||||
let mut v = Vec::with_capacity(capacity);
|
let mut v = Vec::with_capacity(capacity);
|
||||||
v.extend(repeat(0).take(capacity));
|
v.extend(repeat(0).take(capacity));
|
||||||
|
@ -22,15 +80,21 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_slice(sl: &[u8]) -> Buffer {
|
/// allocates a new buffer containing the slice `data`
|
||||||
|
///
|
||||||
|
/// the buffer starts full, its available data size is exactly `data.len()`
|
||||||
|
pub fn from_slice(data: &[u8]) -> Buffer {
|
||||||
Buffer {
|
Buffer {
|
||||||
memory: Vec::from(sl),
|
memory: Vec::from(data),
|
||||||
capacity: sl.len(),
|
capacity: data.len(),
|
||||||
position: 0,
|
position: 0,
|
||||||
end: sl.len()
|
end: data.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// increases the size of the buffer
|
||||||
|
///
|
||||||
|
/// this does nothing if the buffer is already large enough
|
||||||
pub fn grow(&mut self, new_size: usize) -> bool {
|
pub fn grow(&mut self, new_size: usize) -> bool {
|
||||||
if self.capacity >= new_size {
|
if self.capacity >= new_size {
|
||||||
return false;
|
return false;
|
||||||
|
@ -41,22 +105,31 @@ impl Buffer {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns how much data can be read from the buffer
|
||||||
pub fn available_data(&self) -> usize {
|
pub fn available_data(&self) -> usize {
|
||||||
self.end - self.position
|
self.end - self.position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns how much free space is available to write to
|
||||||
pub fn available_space(&self) -> usize {
|
pub fn available_space(&self) -> usize {
|
||||||
self.capacity - self.end
|
self.capacity - self.end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns the underlying vector's size
|
||||||
pub fn capacity(&self) -> usize {
|
pub fn capacity(&self) -> usize {
|
||||||
self.capacity
|
self.capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns true if there is no more data to read
|
||||||
pub fn empty(&self) -> bool {
|
pub fn empty(&self) -> bool {
|
||||||
self.position == self.end
|
self.position == self.end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// advances the position tracker
|
||||||
|
///
|
||||||
|
/// if the position gets past the buffer's half,
|
||||||
|
/// this will call `shift()` to move the remaining data
|
||||||
|
/// to the beginning of the buffer
|
||||||
pub fn consume(&mut self, count: usize) -> usize {
|
pub fn consume(&mut self, count: usize) -> usize {
|
||||||
let cnt = cmp::min(count, self.available_data());
|
let cnt = cmp::min(count, self.available_data());
|
||||||
self.position += cnt;
|
self.position += cnt;
|
||||||
|
@ -67,6 +140,12 @@ impl Buffer {
|
||||||
cnt
|
cnt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// after having written data to the buffer, use this function
|
||||||
|
/// to indicate how many bytes were written
|
||||||
|
///
|
||||||
|
/// if there is not enough available space, this function can call
|
||||||
|
/// `shift()` to move the remaining data to the beginning of the
|
||||||
|
/// buffer
|
||||||
pub fn fill(&mut self, count: usize) -> usize {
|
pub fn fill(&mut self, count: usize) -> usize {
|
||||||
let cnt = cmp::min(count, self.available_space());
|
let cnt = cmp::min(count, self.available_space());
|
||||||
self.end += cnt;
|
self.end += cnt;
|
||||||
|
@ -101,19 +180,27 @@ impl Buffer {
|
||||||
self.position
|
self.position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// moves the position and end trackers to the beginning
|
||||||
|
/// this function does not modify the data
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.position = 0;
|
self.position = 0;
|
||||||
self.end = 0;
|
self.end = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns a slice with all the available data
|
||||||
pub fn data(&self) -> &[u8] {
|
pub fn data(&self) -> &[u8] {
|
||||||
&self.memory[self.position..self.end]
|
&self.memory[self.position..self.end]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns a mutable slice with all the available space to
|
||||||
|
/// write to
|
||||||
pub fn space(&mut self) -> &mut[u8] {
|
pub fn space(&mut self) -> &mut[u8] {
|
||||||
&mut self.memory[self.end..self.capacity]
|
&mut self.memory[self.end..self.capacity]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// moves the data at the beginning of the buffer
|
||||||
|
///
|
||||||
|
/// if the position was more than 0, it is now 0
|
||||||
pub fn shift(&mut self) {
|
pub fn shift(&mut self) {
|
||||||
if self.position > 0 {
|
if self.position > 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -125,6 +212,8 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: this should probably be rewritten, and tested extensively
|
||||||
|
#[doc(hidden)]
|
||||||
pub fn delete_slice(&mut self, start: usize, length: usize) -> Option<usize> {
|
pub fn delete_slice(&mut self, start: usize, length: usize) -> Option<usize> {
|
||||||
if start + length >= self.available_data() {
|
if start + length >= self.available_data() {
|
||||||
return None
|
return None
|
||||||
|
@ -143,6 +232,8 @@ impl Buffer {
|
||||||
Some(self.available_data())
|
Some(self.available_data())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: this should probably be rewritten, and tested extensively
|
||||||
|
#[doc(hidden)]
|
||||||
pub fn replace_slice(&mut self, data: &[u8], start: usize, length: usize) -> Option<usize> {
|
pub fn replace_slice(&mut self, data: &[u8], start: usize, length: usize) -> Option<usize> {
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
if start + length > self.available_data() ||
|
if start + length > self.available_data() ||
|
||||||
|
@ -170,6 +261,8 @@ impl Buffer {
|
||||||
Some(self.available_data())
|
Some(self.available_data())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: this should probably be rewritten, and tested extensively
|
||||||
|
#[doc(hidden)]
|
||||||
pub fn insert_slice(&mut self, data: &[u8], start: usize) -> Option<usize> {
|
pub fn insert_slice(&mut self, data: &[u8], start: usize) -> Option<usize> {
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
if start > self.available_data() ||
|
if start > self.available_data() ||
|
||||||
|
|
Loading…
Reference in New Issue