Skip to content

Instantly share code, notes, and snippets.

@shadowmint
Created February 10, 2015 04:08
Show Gist options
  • Save shadowmint/e341206cf458a74cd3cd to your computer and use it in GitHub Desktop.
Save shadowmint/e341206cf458a74cd3cd to your computer and use it in GitHub Desktop.
use traits::Trait;
use array::ArrayExt;
use array::Array;
use array::Block;
use array::Raw;
use std::default::Default;
/// A set of errors to associate with the buffer
#[derive(Debug)]
pub enum BufferError {
/// A size bound was invalid
InvalidSize,
/// A set of bounded arrays was passed, but they didn't match the required size
SizeMismatch
}
/// A big fixed size pixel buffer
pub struct Buffer<T: Default + Copy> {
/// The length of this buffer in each dimension
dim: Trait<Array<u32> + 'static>,
/// The buffer for this buffer
data: Trait<Array<T> + 'static>
}
/// Temporary view into a buffer
pub struct BufferTmp<'a, T: Default + Copy + 'static> {
/// Parent we borrowed to get this tmp from
parent: &'a Buffer<T>,
/// The offset into the parent for this buffer
offset: Trait<Array<u32> + 'static>,
/// The size of this buffer
dim: Trait<Array<u32> + 'static>,
}
/// Temporary view into a buffer which is writable
pub struct BufferTmpMut<'a, T: Default + Copy + 'static> {
/// Parent we borrowed to get this tmp from
parent: &'a mut Buffer<T>
/// The offset into the parent for this buffer
offset: Trait<Array<u32> + 'static>,
/// The size of this buffer
dim: Trait<Array<u32> + 'static>,
}
impl<T: Default + Copy + 'static> Buffer<T> {
/// Create a new buffer from an external source
/// @param data The raw data buffer, eg. from c
/// @param dim The size of the buffer; eg. &[100, 100]
pub fn new(data:*mut T, dim:&[u32]) -> Buffer<T> {
let mut dims = Block::<u32>::with(dim);
let mut total = 1u32;
for i in dim.iter() {
total = total * *i;
}
return Buffer {
dim: dims,
data: Raw::new(data, total as usize)
};
}
/// Create a new buffer from an external source
/// @param dim The size of the buffer; eg. &[100, 100]
pub fn alloc(dim:&[u32]) -> Buffer<T> {
let mut dims = Block::<u32>::with(dim);
let mut total = 1u32;
for i in dim.iter() {
total = total * *i;
}
return Buffer {
dim: dims,
data: Block::new(total as usize)
};
}
/// Create a raw buffer with an offset and size from an existing on
pub fn sub<'a>(&'a self, offset:&[u32], size:&[u32]) -> Result<BufferTmp<'a, T>, BufferError> {
let dims = self.size();
if offset.len() != dims.len() { return Err(BufferError::SizeMismatch); }
if size.len() != dims.len() { return Err(BufferError::SizeMismatch); }
for i in range(0, dims.len()) {
if (offset[i] + size[i]) > dims[i] {
return Err(BufferError::InvalidSize);
}
}
return Ok(BufferTmp {
parent: self,
dim: Block::<u32>::with(size),
offset: Block::<u32>::with(offset)
});
}
/// Create a mut raw buffer with an offset and size from an existing on
pub fn mut_sub<'a>(&'a mut self, offset:&[u32], size:&[u32]) -> Result<TmpMutBuffer<'a, T>, BufferError> {
{
let dims = self.size();
if offset.len() != dims.len() { return Err(BufferError::SizeMismatch); }
if size.len() != dims.len() { return Err(BufferError::SizeMismatch); }
for i in range(0, dims.len()) {
if (offset[i] + size[i]) > dims[i] {
return Err(BufferError::InvalidSize);
}
}
}
return Ok(TmpMutBuffer {
parent: self,
dim: Block::<u32>::with(size),
offset: Block::<u32>::with(offset)
});
}
/// Return the size of the buffer
pub fn size(&self) -> &[u32] {
return (*self.dim).as_slice();
}
/// Return a copy of the inner pointer
pub fn data(&self) -> *const T {
return (&*self.data).data();
}
}
impl<'a, T: Default + Copy + 'static> BufferTmp<'a, T> {
/// Return the size of the buffer
pub fn size(&self) -> &[u32] {
return (*self.dim).as_slice();
}
/// Return a copy of the inner pointer
pub fn data(&self) -> *const T {
let size = self.parent.size();
let offset = (*self.offset).as_slice();
return (&*self.parent).data();
}
}
#[cfg(test)]
mod test {
use super::Buffer;
#[test]
fn test_create_raw_buffer() {
let _ = Buffer::new(0 as *mut u8, &[10, 10]);
}
#[test]
fn test_create_alloc_buffer() {
let _ = Buffer::<u8>::alloc(&[10, 10]);
}
#[test]
fn test_create_sub_buffer() {
let buffer = Buffer::<u8>::alloc(&[10, 10]);
assert!(buffer.sub(&[0, 0], &[10, 10]).is_ok());
assert!(buffer.sub(&[1, 0], &[10, 10]).is_err());
assert!(buffer.sub(&[0, 1], &[10, 10]).is_err());
assert!(buffer.sub(&[1, 0], &[10, 10]).is_err());
assert!(buffer.sub(&[1, 0], &[10, 10]).is_err());
}
#[test]
fn test_create_mut_sub_buffer() {
let mut buffer = Buffer::<u8>::alloc(&[10, 10]);
assert!(buffer.mut_sub(&[0, 0], &[10, 10]).is_ok());
assert!(buffer.mut_sub(&[1, 0], &[10, 10]).is_err());
assert!(buffer.mut_sub(&[0, 1], &[10, 10]).is_err());
assert!(buffer.mut_sub(&[1, 0], &[10, 10]).is_err());
assert!(buffer.mut_sub(&[1, 0], &[10, 10]).is_err());
}
}
doug:rust-pixelbuffer doug$ cargo test
Compiling pixelbuffer v0.0.1 (file:///Users/doug/dev/rust-all/rust-pixelbuffer)
src/buffer.rs:133:39: 133:55 error: inherent implementations are not allowed for types not defined in the current module
src/buffer.rs:133:39: 133:55 error: inherent implementations are not allowed for types not defined in the current module
src/buffer.rs:133 impl<'a, T: Default + Copy + 'static> BufferTmp<'a, T> {
src/buffer.rs:133 impl<'a, T: Default + Copy + 'static> BufferTmp<'a, T> {
^~~~~~~~~~~~~~~~
^~~~~~~~~~~~~~~~
error: aborting due to previous error
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
Could not compile `pixelbuffer`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment