diff --git a/src/heap.rs b/src/alloc/heap.rs similarity index 93% rename from src/heap.rs rename to src/alloc/heap.rs index d78ef6c..0de08eb 100644 --- a/src/heap.rs +++ b/src/alloc/heap.rs @@ -4,14 +4,8 @@ use std::ops::DerefMut; const MAX_ALLOC_SIZE: usize = usize::MAX; -pub fn allocate(len: usize) -> MemRef { - HEAP.allocate(len) -} - pub struct Heap; -pub static HEAP: Heap = Heap; - impl Heap { pub fn allocate(&self, len: usize) -> MemRef { // Make sure that the allocation is within the permitted range diff --git a/src/alloc.rs b/src/alloc/mod.rs similarity index 96% rename from src/alloc.rs rename to src/alloc/mod.rs index 39312f2..2d715bf 100644 --- a/src/alloc.rs +++ b/src/alloc/mod.rs @@ -1,6 +1,14 @@ +mod heap; + +pub use self::heap::{Heap}; + use std::{mem, ptr}; use std::sync::atomic::{AtomicUsize, Ordering}; +pub fn heap(len: usize) -> MemRef { + Heap.allocate(len) +} + /// Allocates memory to be used by Bufs or Bytes. Allows allocating memory /// using alternate stratgies than the default Rust heap allocator. Also does /// not require that allocations are continuous in memory. diff --git a/src/byte_buf.rs b/src/buf/byte.rs similarity index 98% rename from src/byte_buf.rs rename to src/buf/byte.rs index cf8fc4d..6b6cdb5 100644 --- a/src/byte_buf.rs +++ b/src/buf/byte.rs @@ -1,4 +1,4 @@ -use {alloc, heap, Bytes, SeqByteStr, MAX_CAPACITY}; +use {alloc, Bytes, SeqByteStr, MAX_CAPACITY}; use traits::{Buf, MutBuf, MutBufExt, ByteStr}; use std::{cmp, ptr}; @@ -59,7 +59,7 @@ impl ByteBuf { capacity = capacity.next_power_of_two(); // Allocate the memory - let mem = heap::allocate(capacity as usize); + let mem = alloc::heap(capacity as usize); // If the allocation failed, return a blank buf if mem.is_none() { diff --git a/src/buf/mod.rs b/src/buf/mod.rs new file mode 100644 index 0000000..7e50007 --- /dev/null +++ b/src/buf/mod.rs @@ -0,0 +1,364 @@ +mod byte; +mod ring; +mod sink; +mod slice; +mod source; + +pub use self::byte::{ByteBuf, MutByteBuf, ROByteBuf}; +pub use self::ring::RingBuf; +pub use self::slice::{SliceBuf, MutSliceBuf}; + +use {BufError, RopeBuf}; +use std::{cmp, fmt, io, ptr}; + +/// A trait for values that provide sequential read access to bytes. +pub trait Buf { + + /// Returns the number of bytes that can be accessed from the Buf + fn remaining(&self) -> usize; + + /// Returns a slice starting at the current Buf position and of length + /// between 0 and `Buf::remaining()`. + fn bytes<'a>(&'a self) -> &'a [u8]; + + /// Advance the internal cursor of the Buf + fn advance(&mut self, cnt: usize); + + /// Returns true if there are any more bytes to consume + fn has_remaining(&self) -> bool { + self.remaining() > 0 + } + + /// Read bytes from the `Buf` into the given slice and advance the cursor by + /// the number of bytes read. + /// + /// If there are fewer bytes remaining than is needed to satisfy the + /// request (aka `dst.len()` > self.remaining()`), then + /// `Err(BufError::Overflow)` is returned. + /// + /// ``` + /// use bytes::{SliceBuf, Buf}; + /// + /// let mut buf = SliceBuf::wrap(b"hello world"); + /// let mut dst = [0; 5]; + /// + /// buf.read_slice(&mut dst); + /// assert_eq!(b"hello", &dst); + /// assert_eq!(6, buf.remaining()); + /// ``` + fn read_slice(&mut self, dst: &mut [u8]) -> usize { + let mut off = 0; + let len = cmp::min(dst.len(), self.remaining()); + + while off < len { + let mut cnt; + + unsafe { + let src = self.bytes(); + cnt = cmp::min(src.len(), len - off); + + ptr::copy_nonoverlapping( + src.as_ptr(), dst[off..].as_mut_ptr(), cnt); + + off += src.len(); + } + + self.advance(cnt); + } + + len + } + + /// Read a single byte from the `Buf` + fn read_byte(&mut self) -> Option { + let mut dst = [0]; + + if self.read_slice(&mut dst) == 0 { + return None; + } + + Some(dst[0]) + } +} + +/// An extension trait providing extra functions applicable to all `Buf` values. +pub trait BufExt { + + /// Read bytes from this Buf into the given sink and advance the cursor by + /// the number of bytes read. + fn read(&mut self, dst: S) -> Result; +} + +/// A trait for values that provide sequential write access to bytes. +pub trait MutBuf : Sized { + + /// Returns the number of bytes that can be accessed from the Buf + fn remaining(&self) -> usize; + + /// Advance the internal cursor of the Buf + fn advance(&mut self, cnt: usize); + + /// Returns true if there are any more bytes to consume + fn has_remaining(&self) -> bool { + self.remaining() > 0 + } + + /// Returns a mutable slice starting at the current Buf position and of + /// length between 0 and `Buf::remaining()`. + fn mut_bytes<'a>(&'a mut self) -> &'a mut [u8]; + + /// Read bytes from this Buf into the given slice and advance the cursor by + /// the number of bytes read. + /// + /// If there are fewer bytes remaining than is needed to satisfy the + /// request (aka `dst.len()` > self.remaining()`), then + /// `Err(BufError::Overflow)` is returned. + /// + /// ``` + /// use bytes::{MutSliceBuf, Buf, MutBuf}; + /// + /// let mut dst = [0; 6]; + /// + /// { + /// let mut buf = MutSliceBuf::wrap(&mut dst); + /// buf.write_slice(b"hello"); + /// + /// assert_eq!(1, buf.remaining()); + /// } + /// + /// assert_eq!(b"hello\0", &dst); + /// ``` + fn write_slice(&mut self, src: &[u8]) -> usize { + let mut off = 0; + let len = cmp::min(src.len(), self.remaining()); + + while off < len { + let mut cnt; + + unsafe { + let dst = self.mut_bytes(); + cnt = cmp::min(dst.len(), len - off); + + ptr::copy_nonoverlapping( + src[off..].as_ptr(), + dst.as_mut_ptr(), + cnt); + + off += cnt; + } + + self.advance(cnt); + } + + len + } + + /// Write a single byte to the `MuBuf` + fn write_byte(&mut self, byte: u8) -> bool { + let src = [byte]; + + if self.write_slice(&src) == 0 { + return false; + } + + true + } +} + +/// An extension trait providing extra functions applicable to all `MutBuf` values. +pub trait MutBufExt { + + /// Write bytes from the given source into the current `MutBuf` and advance + /// the cursor by the number of bytes written. + fn write(&mut self, src: S) -> Result; +} + +/* + * + * ===== *Ext impls ===== + * + */ + +impl BufExt for B { + fn read(&mut self, dst: S) -> Result { + dst.sink(self) + } +} + +impl MutBufExt for B { + fn write(&mut self, src: S) -> Result { + src.fill(self) + } +} + +/* + * + * ===== Sink / Source ===== + * + */ + +/// A value that reads bytes from a Buf into itself +pub trait Sink { + type Error; + + fn sink(self, buf: &mut B) -> Result; +} + +/// A value that writes bytes from itself into a `MutBuf`. +pub trait Source { + type Error; + + fn fill(self, buf: &mut B) -> Result; +} + +impl<'a> Sink for &'a mut [u8] { + type Error = BufError; + + fn sink(self, buf: &mut B) -> Result { + Ok(buf.read_slice(self)) + } +} + +impl<'a> Sink for &'a mut Vec { + type Error = BufError; + + fn sink(self, buf: &mut B) -> Result { + use std::slice; + + self.clear(); + + let rem = buf.remaining(); + let cap = self.capacity(); + + // Ensure that the vec is big enough + if rem > self.capacity() { + self.reserve(rem - cap); + } + + unsafe { + { + let dst = &mut self[..]; + let cnt = buf.read_slice(slice::from_raw_parts_mut(dst.as_mut_ptr(), rem)); + + debug_assert!(cnt == rem); + } + + self.set_len(rem); + } + + Ok(rem) + } +} + +impl<'a> Source for &'a [u8] { + type Error = BufError; + + fn fill(self, buf: &mut B) -> Result { + Ok(buf.write_slice(self)) + } +} + +impl<'a> Source for &'a Vec { + type Error = BufError; + + fn fill(self, buf: &mut B) -> Result { + Ok(buf.write_slice(self.as_ref())) + } +} + + +impl<'a, R: io::Read+'a> Source for &'a mut R { + type Error = io::Error; + + fn fill(self, buf: &mut B) -> Result { + let mut cnt = 0; + + while buf.has_remaining() { + let i = try!(self.read(buf.mut_bytes())); + + if i == 0 { + break; + } + + buf.advance(i); + cnt += i; + } + + Ok(cnt) + } +} + +/* + * + * ===== Buf impls ===== + * + */ + +impl Buf for Box { + fn remaining(&self) -> usize { + (**self).remaining() + } + + fn bytes(&self) -> &[u8] { + (**self).bytes() + } + + fn advance(&mut self, cnt: usize) { + (**self).advance(cnt); + } + + fn read_slice(&mut self, dst: &mut [u8]) -> usize { + (**self).read_slice(dst) + } +} + +impl fmt::Debug for Box { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "Box {{ remaining: {} }}", self.remaining()) + } +} + +/* + * + * ===== Read impls ===== + * + */ + +macro_rules! impl_read { + ($ty:ty) => { + impl io::Read for $ty { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + if !self.has_remaining() { + return Ok(0); + } + + Ok(self.read_slice(buf)) + } + } + } +} + +impl_read!(ByteBuf); +impl_read!(ROByteBuf); +impl_read!(RopeBuf); +impl_read!(Box); + +macro_rules! impl_write { + ($ty:ty) => { + impl io::Write for $ty { + fn write(&mut self, buf: &[u8]) -> io::Result { + if !self.has_remaining() { + return Ok(0); + } + + Ok(self.write_slice(buf)) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + } + } +} + +impl_write!(MutByteBuf); diff --git a/src/ring.rs b/src/buf/ring.rs similarity index 97% rename from src/ring.rs rename to src/buf/ring.rs index e322e4d..7f8a0e3 100644 --- a/src/ring.rs +++ b/src/buf/ring.rs @@ -1,4 +1,4 @@ -use {alloc, heap, Buf, MutBuf}; +use {alloc, Buf, MutBuf}; use std::{cmp, fmt, io, ptr}; /// Buf backed by a continous chunk of memory. Maintains a read cursor and a @@ -27,7 +27,7 @@ impl RingBuf { // Round to the next power of 2 for better alignment capacity = capacity.next_power_of_two(); - let mem = heap::allocate(capacity as usize); + let mem = alloc::heap(capacity as usize); RingBuf { ptr: mem, diff --git a/src/buf/sink.rs b/src/buf/sink.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/slice.rs b/src/buf/slice.rs similarity index 94% rename from src/slice.rs rename to src/buf/slice.rs index 1d23318..eaa2cf3 100644 --- a/src/slice.rs +++ b/src/buf/slice.rs @@ -1,6 +1,8 @@ use std::cmp; use {Buf, MutBuf}; +// TODO: Rename -> Cursor. Use as buf for various byte strings + pub struct SliceBuf<'a> { bytes: &'a [u8], pos: usize diff --git a/src/buf/source.rs b/src/buf/source.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/lib.rs b/src/lib.rs index c4f66bb..3fce9ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,24 +1,36 @@ #![crate_name = "bytes"] #![unstable] -pub use byte_buf::{ByteBuf, ROByteBuf, MutByteBuf}; -pub use byte_str::{SeqByteStr, SmallByteStr, SmallByteStrBuf}; -pub use bytes::Bytes; -pub use ring::RingBuf; -pub use rope::{Rope, RopeBuf}; -pub use slice::{SliceBuf, MutSliceBuf}; +pub mod alloc; +mod buf; +mod str; -use std::{cmp, fmt, io, ops, ptr, u32}; -use std::any::Any; +pub use buf::{ + Buf, + BufExt, + MutBuf, + MutBufExt, + ByteBuf, + MutByteBuf, + RingBuf, + ROByteBuf, + SliceBuf, + MutSliceBuf, + Source, + Sink +}; +pub use str::{ + ByteStr, + Bytes, + Rope, + RopeBuf, + SeqByteStr, + SmallByteStr, + SmallByteStrBuf, + ToBytes, +}; -mod alloc; -mod byte_buf; -mod byte_str; -mod bytes; -mod heap; -mod ring; -mod rope; -mod slice; +use std::u32; pub mod traits { //! All traits are re-exported here to allow glob imports. @@ -27,527 +39,6 @@ pub mod traits { const MAX_CAPACITY: usize = u32::MAX as usize; -/// A trait for values that provide sequential read access to bytes. -pub trait Buf { - - /// Returns the number of bytes that can be accessed from the Buf - fn remaining(&self) -> usize; - - /// Returns a slice starting at the current Buf position and of length - /// between 0 and `Buf::remaining()`. - fn bytes<'a>(&'a self) -> &'a [u8]; - - /// Advance the internal cursor of the Buf - fn advance(&mut self, cnt: usize); - - /// Returns true if there are any more bytes to consume - fn has_remaining(&self) -> bool { - self.remaining() > 0 - } - - /// Read bytes from the `Buf` into the given slice and advance the cursor by - /// the number of bytes read. - /// - /// If there are fewer bytes remaining than is needed to satisfy the - /// request (aka `dst.len()` > self.remaining()`), then - /// `Err(BufError::Overflow)` is returned. - /// - /// ``` - /// use bytes::{SliceBuf, Buf}; - /// - /// let mut buf = SliceBuf::wrap(b"hello world"); - /// let mut dst = [0; 5]; - /// - /// buf.read_slice(&mut dst); - /// assert_eq!(b"hello", &dst); - /// assert_eq!(6, buf.remaining()); - /// ``` - fn read_slice(&mut self, dst: &mut [u8]) -> usize { - let mut off = 0; - let len = cmp::min(dst.len(), self.remaining()); - - while off < len { - let mut cnt; - - unsafe { - let src = self.bytes(); - cnt = cmp::min(src.len(), len - off); - - ptr::copy_nonoverlapping( - src.as_ptr(), dst[off..].as_mut_ptr(), cnt); - - off += src.len(); - } - - self.advance(cnt); - } - - len - } - - /// Read a single byte from the `Buf` - fn read_byte(&mut self) -> Option { - let mut dst = [0]; - - if self.read_slice(&mut dst) == 0 { - return None; - } - - Some(dst[0]) - } -} - -/// An extension trait providing extra functions applicable to all `Buf` values. -pub trait BufExt { - - /// Read bytes from this Buf into the given sink and advance the cursor by - /// the number of bytes read. - fn read(&mut self, dst: S) -> Result; -} - -/// A trait for values that provide sequential write access to bytes. -pub trait MutBuf : Sized { - - /// Returns the number of bytes that can be accessed from the Buf - fn remaining(&self) -> usize; - - /// Advance the internal cursor of the Buf - fn advance(&mut self, cnt: usize); - - /// Returns true if there are any more bytes to consume - fn has_remaining(&self) -> bool { - self.remaining() > 0 - } - - /// Returns a mutable slice starting at the current Buf position and of - /// length between 0 and `Buf::remaining()`. - fn mut_bytes<'a>(&'a mut self) -> &'a mut [u8]; - - /// Read bytes from this Buf into the given slice and advance the cursor by - /// the number of bytes read. - /// - /// If there are fewer bytes remaining than is needed to satisfy the - /// request (aka `dst.len()` > self.remaining()`), then - /// `Err(BufError::Overflow)` is returned. - /// - /// ``` - /// use bytes::{MutSliceBuf, Buf, MutBuf}; - /// - /// let mut dst = [0; 6]; - /// - /// { - /// let mut buf = MutSliceBuf::wrap(&mut dst); - /// buf.write_slice(b"hello"); - /// - /// assert_eq!(1, buf.remaining()); - /// } - /// - /// assert_eq!(b"hello\0", &dst); - /// ``` - fn write_slice(&mut self, src: &[u8]) -> usize { - let mut off = 0; - let len = cmp::min(src.len(), self.remaining()); - - while off < len { - let mut cnt; - - unsafe { - let dst = self.mut_bytes(); - cnt = cmp::min(dst.len(), len - off); - - ptr::copy_nonoverlapping( - src[off..].as_ptr(), - dst.as_mut_ptr(), - cnt); - - off += cnt; - } - - self.advance(cnt); - } - - len - } - - /// Write a single byte to the `MuBuf` - fn write_byte(&mut self, byte: u8) -> bool { - let src = [byte]; - - if self.write_slice(&src) == 0 { - return false; - } - - true - } -} - -/// An extension trait providing extra functions applicable to all `MutBuf` values. -pub trait MutBufExt { - - /// Write bytes from the given source into the current `MutBuf` and advance - /// the cursor by the number of bytes written. - fn write(&mut self, src: S) -> Result; -} - -/* - * - * ===== ByteStr ===== - * - */ - -/// An immutable sequence of bytes. Operations will not mutate the original -/// value. Since only immutable access is permitted, operations do not require -/// copying (though, sometimes copying will happen as an optimization). -pub trait ByteStr : Clone + Sized + Send + Sync + Any + ToBytes + ops::Index + 'static { - - // Until HKT lands, the buf must be bound by 'static - type Buf: Buf+'static; - - /// Returns a read-only `Buf` for accessing the byte contents of the - /// `ByteStr`. - fn buf(&self) -> Self::Buf; - - /// Returns a new `Bytes` value representing the concatenation of `self` - /// with the given `Bytes`. - fn concat(&self, other: &B) -> Bytes; - - /// Returns the number of bytes in the ByteStr - fn len(&self) -> usize; - - /// Returns true if the length of the `ByteStr` is 0 - fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Returns a new ByteStr value containing the byte range between `begin` - /// (inclusive) and `end` (exclusive) - fn slice(&self, begin: usize, end: usize) -> Bytes; - - /// Returns a new ByteStr value containing the byte range starting from - /// `begin` (inclusive) to the end of the byte str. - /// - /// Equivalent to `bytes.slice(begin, bytes.len())` - fn slice_from(&self, begin: usize) -> Bytes { - self.slice(begin, self.len()) - } - - /// Returns a new ByteStr value containing the byte range from the start up - /// to `end` (exclusive). - /// - /// Equivalent to `bytes.slice(0, end)` - fn slice_to(&self, end: usize) -> Bytes { - self.slice(0, end) - } - - /// Divides the value into two `Bytes` at the given index. - /// - /// The first will contain all bytes from `[0, mid]` (excluding the index - /// `mid` itself) and the second will contain all indices from `[mid, len)` - /// (excluding the index `len` itself). - /// - /// Panics if `mid > len`. - fn split_at(&self, mid: usize) -> (Bytes, Bytes) { - (self.slice_to(mid), self.slice_from(mid)) - } -} - -macro_rules! impl_parteq { - ($ty:ty) => { - impl cmp::PartialEq for $ty { - fn eq(&self, other: &B) -> bool { - if self.len() != other.len() { - return false; - } - - let mut buf1 = self.buf(); - let mut buf2 = self.buf(); - - while buf1.has_remaining() { - let len; - - { - let b1 = buf1.bytes(); - let b2 = buf2.bytes(); - - len = cmp::min(b1.len(), b2.len()); - - if b1[..len] != b2[..len] { - return false; - } - } - - buf1.advance(len); - buf2.advance(len); - } - - true - } - - fn ne(&self, other: &B) -> bool { - return !self.eq(other) - } - } - } -} - -impl_parteq!(SeqByteStr); -impl_parteq!(SmallByteStr); -impl_parteq!(Bytes); -impl_parteq!(Rope); - -macro_rules! impl_eq { - ($ty:ty) => { - impl cmp::Eq for $ty {} - } -} - -impl_eq!(Bytes); - -/* - * - * ===== ToBytes ===== - * - */ - -pub trait ToBytes { - /// Consumes the value and returns a `Bytes` instance containing - /// identical bytes - fn to_bytes(self) -> Bytes; -} - -impl<'a> ToBytes for &'a [u8] { - fn to_bytes(self) -> Bytes { - Bytes::from_slice(self) - } -} - -impl<'a> ToBytes for &'a Vec { - fn to_bytes(self) -> Bytes { - (&self[..]).to_bytes() - } -} - -/* - * - * ===== *Ext impls ===== - * - */ - -impl BufExt for B { - fn read(&mut self, dst: S) -> Result { - dst.sink(self) - } -} - -impl MutBufExt for B { - fn write(&mut self, src: S) -> Result { - src.fill(self) - } -} - -/* - * - * ===== Sink / Source ===== - * - */ - -/// A value that reads bytes from a Buf into itself -pub trait Sink { - type Error; - - fn sink(self, buf: &mut B) -> Result; -} - -/// A value that writes bytes from itself into a `MutBuf`. -pub trait Source { - type Error; - - fn fill(self, buf: &mut B) -> Result; -} - -impl<'a> Sink for &'a mut [u8] { - type Error = BufError; - - fn sink(self, buf: &mut B) -> Result { - Ok(buf.read_slice(self)) - } -} - -impl<'a> Sink for &'a mut Vec { - type Error = BufError; - - fn sink(self, buf: &mut B) -> Result { - use std::slice; - - self.clear(); - - let rem = buf.remaining(); - let cap = self.capacity(); - - // Ensure that the vec is big enough - if rem > self.capacity() { - self.reserve(rem - cap); - } - - unsafe { - { - let dst = &mut self[..]; - let cnt = buf.read_slice(slice::from_raw_parts_mut(dst.as_mut_ptr(), rem)); - - debug_assert!(cnt == rem); - } - - self.set_len(rem); - } - - Ok(rem) - } -} - -impl<'a> Source for &'a [u8] { - type Error = BufError; - - fn fill(self, buf: &mut B) -> Result { - Ok(buf.write_slice(self)) - } -} - -impl<'a> Source for &'a Vec { - type Error = BufError; - - fn fill(self, buf: &mut B) -> Result { - Ok(buf.write_slice(self.as_ref())) - } -} - -impl<'a> Source for &'a Bytes { - type Error = BufError; - - fn fill(self, dst: &mut B) -> Result { - let mut src = self.buf(); - let mut res = 0; - - while src.has_remaining() && dst.has_remaining() { - let mut l; - - { - let s = src.bytes(); - let d = dst.mut_bytes(); - l = cmp::min(s.len(), d.len()); - - unsafe { - ptr::copy_nonoverlapping( - s.as_ptr(), - d.as_mut_ptr(), - l); - } - } - - src.advance(l); - dst.advance(l); - - res += l; - } - - Ok(res) - } -} - -impl<'a, R: io::Read+'a> Source for &'a mut R { - type Error = io::Error; - - fn fill(self, buf: &mut B) -> Result { - let mut cnt = 0; - - while buf.has_remaining() { - let i = try!(self.read(buf.mut_bytes())); - - if i == 0 { - break; - } - - buf.advance(i); - cnt += i; - } - - Ok(cnt) - } -} - -/* - * - * ===== Buf impls ===== - * - */ - -impl Buf for Box { - fn remaining(&self) -> usize { - (**self).remaining() - } - - fn bytes(&self) -> &[u8] { - (**self).bytes() - } - - fn advance(&mut self, cnt: usize) { - (**self).advance(cnt); - } - - fn read_slice(&mut self, dst: &mut [u8]) -> usize { - (**self).read_slice(dst) - } -} - -impl fmt::Debug for Box { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "Box {{ remaining: {} }}", self.remaining()) - } -} - -/* - * - * ===== Read impls ===== - * - */ - -macro_rules! impl_read { - ($ty:ty) => { - impl io::Read for $ty { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - if !self.has_remaining() { - return Ok(0); - } - - Ok(self.read_slice(buf)) - } - } - } -} - -impl_read!(ByteBuf); -impl_read!(ROByteBuf); -impl_read!(RopeBuf); -impl_read!(Box); - -macro_rules! impl_write { - ($ty:ty) => { - impl io::Write for $ty { - fn write(&mut self, buf: &[u8]) -> io::Result { - if !self.has_remaining() { - return Ok(0); - } - - Ok(self.write_slice(buf)) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } - } - } -} - -impl_write!(MutByteBuf); /* * @@ -560,43 +51,3 @@ pub enum BufError { Underflow, Overflow, } - -/* - * - * ===== Internal utilities ===== - * - */ - -fn debug(bytes: &B, name: &str, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut buf = bytes.buf(); - - try!(write!(fmt, "{}[len={}; ", name, bytes.len())); - - let mut rem = 128; - - while let Some(byte) = buf.read_byte() { - if rem > 0 { - if is_ascii(byte) { - try!(write!(fmt, "{}", byte as char)); - } else { - try!(write!(fmt, "\\x{:02X}", byte)); - } - - rem -= 1; - } else { - try!(write!(fmt, " ... ")); - break; - } - } - - try!(write!(fmt, "]")); - - Ok(()) -} - -fn is_ascii(byte: u8) -> bool { - match byte { - 10 | 13 | 32...126 => true, - _ => false, - } -} diff --git a/src/byte_str.rs b/src/str/byte_str.rs similarity index 100% rename from src/byte_str.rs rename to src/str/byte_str.rs diff --git a/src/bytes.rs b/src/str/bytes.rs similarity index 88% rename from src/bytes.rs rename to src/str/bytes.rs index 9db426e..a994a69 100644 --- a/src/bytes.rs +++ b/src/str/bytes.rs @@ -1,6 +1,6 @@ -use {ByteBuf, SmallByteStr}; +use {ByteBuf, MutBuf, SmallByteStr, Source, BufError}; use traits::{Buf, ByteStr, ToBytes}; -use std::{fmt, mem, ops, ptr}; +use std::{cmp, fmt, mem, ops, ptr}; use std::any::{Any, TypeId}; const INLINE: usize = 1; @@ -194,6 +194,39 @@ impl Drop for Bytes { unsafe impl Send for Bytes { } unsafe impl Sync for Bytes { } +impl<'a> Source for &'a Bytes { + type Error = BufError; + + fn fill(self, dst: &mut B) -> Result { + let mut src = ByteStr::buf(self); + let mut res = 0; + + while src.has_remaining() && dst.has_remaining() { + let mut l; + + { + let s = src.bytes(); + let d = dst.mut_bytes(); + l = cmp::min(s.len(), d.len()); + + unsafe { + ptr::copy_nonoverlapping( + s.as_ptr(), + d.as_mut_ptr(), + l); + } + } + + src.advance(l); + dst.advance(l); + + res += l; + } + + Ok(res) + } +} + trait ByteStrPriv { fn buf(&self) -> Box; diff --git a/src/str/mod.rs b/src/str/mod.rs new file mode 100644 index 0000000..7afd544 --- /dev/null +++ b/src/str/mod.rs @@ -0,0 +1,185 @@ +mod byte_str; +mod bytes; +mod rope; + +pub use self::byte_str::{SeqByteStr, SmallByteStr, SmallByteStrBuf}; +pub use self::bytes::Bytes; +pub use self::rope::{Rope, RopeBuf}; + +use {Buf}; +use std::{cmp, fmt, ops}; +use std::any::Any; + +/// An immutable sequence of bytes. Operations will not mutate the original +/// value. Since only immutable access is permitted, operations do not require +/// copying (though, sometimes copying will happen as an optimization). +pub trait ByteStr : Clone + Sized + Send + Sync + Any + ToBytes + ops::Index + 'static { + + // Until HKT lands, the buf must be bound by 'static + type Buf: Buf+'static; + + /// Returns a read-only `Buf` for accessing the byte contents of the + /// `ByteStr`. + fn buf(&self) -> Self::Buf; + + /// Returns a new `Bytes` value representing the concatenation of `self` + /// with the given `Bytes`. + fn concat(&self, other: &B) -> Bytes; + + /// Returns the number of bytes in the ByteStr + fn len(&self) -> usize; + + /// Returns true if the length of the `ByteStr` is 0 + fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns a new ByteStr value containing the byte range between `begin` + /// (inclusive) and `end` (exclusive) + fn slice(&self, begin: usize, end: usize) -> Bytes; + + /// Returns a new ByteStr value containing the byte range starting from + /// `begin` (inclusive) to the end of the byte str. + /// + /// Equivalent to `bytes.slice(begin, bytes.len())` + fn slice_from(&self, begin: usize) -> Bytes { + self.slice(begin, self.len()) + } + + /// Returns a new ByteStr value containing the byte range from the start up + /// to `end` (exclusive). + /// + /// Equivalent to `bytes.slice(0, end)` + fn slice_to(&self, end: usize) -> Bytes { + self.slice(0, end) + } + + /// Divides the value into two `Bytes` at the given index. + /// + /// The first will contain all bytes from `[0, mid]` (excluding the index + /// `mid` itself) and the second will contain all indices from `[mid, len)` + /// (excluding the index `len` itself). + /// + /// Panics if `mid > len`. + fn split_at(&self, mid: usize) -> (Bytes, Bytes) { + (self.slice_to(mid), self.slice_from(mid)) + } +} + +macro_rules! impl_parteq { + ($ty:ty) => { + impl cmp::PartialEq for $ty { + fn eq(&self, other: &B) -> bool { + if self.len() != other.len() { + return false; + } + + let mut buf1 = self.buf(); + let mut buf2 = self.buf(); + + while buf1.has_remaining() { + let len; + + { + let b1 = buf1.bytes(); + let b2 = buf2.bytes(); + + len = cmp::min(b1.len(), b2.len()); + + if b1[..len] != b2[..len] { + return false; + } + } + + buf1.advance(len); + buf2.advance(len); + } + + true + } + + fn ne(&self, other: &B) -> bool { + return !self.eq(other) + } + } + } +} + +impl_parteq!(SeqByteStr); +impl_parteq!(SmallByteStr); +impl_parteq!(Bytes); +impl_parteq!(Rope); + +macro_rules! impl_eq { + ($ty:ty) => { + impl cmp::Eq for $ty {} + } +} + +impl_eq!(Bytes); + +/* + * + * ===== ToBytes ===== + * + */ + +pub trait ToBytes { + /// Consumes the value and returns a `Bytes` instance containing + /// identical bytes + fn to_bytes(self) -> Bytes; +} + +impl<'a> ToBytes for &'a [u8] { + fn to_bytes(self) -> Bytes { + Bytes::from_slice(self) + } +} + +impl<'a> ToBytes for &'a Vec { + fn to_bytes(self) -> Bytes { + (&self[..]).to_bytes() + } +} + + + +/* + * + * ===== Internal utilities ===== + * + */ + +fn debug(bytes: &B, name: &str, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut buf = bytes.buf(); + + try!(write!(fmt, "{}[len={}; ", name, bytes.len())); + + let mut rem = 128; + + while let Some(byte) = buf.read_byte() { + if rem > 0 { + if is_ascii(byte) { + try!(write!(fmt, "{}", byte as char)); + } else { + try!(write!(fmt, "\\x{:02X}", byte)); + } + + rem -= 1; + } else { + try!(write!(fmt, " ... ")); + break; + } + } + + try!(write!(fmt, "]")); + + Ok(()) +} + +fn is_ascii(byte: u8) -> bool { + match byte { + 10 | 13 | 32...126 => true, + _ => false, + } +} diff --git a/src/rope.rs b/src/str/rope.rs similarity index 100% rename from src/rope.rs rename to src/str/rope.rs