glium::implement_buffer_content! [] [src]

macro_rules! implement_buffer_content {
    (__as_item $i:item) => {$i};

    (__impl $struct_name:ident [$($gs:tt)*]) => {
        implement_buffer_content! { __as_item
            unsafe impl<$($gs)*> $crate::buffer::Content for $struct_name<$($gs)*> {
                type Owned = Box<$struct_name<$($gs)*>>;

                #[inline]
                fn read<F, E>(size: usize, f: F) -> ::std::result::Result<Box<$struct_name<$($gs)*>>, E>
                              where F: FnOnce(&mut $struct_name<$($gs)*>) -> ::std::result::Result<(), E>
                {
                    use std::mem;

                    assert!(<$struct_name as $crate::buffer::Content>::is_size_suitable(size));

                    let mut storage: Vec<u8> = Vec::with_capacity(size);
                    unsafe { storage.set_len(size) };
                    let storage = storage.into_boxed_slice();
                    let mut storage: Box<$struct_name<$($gs)*>> = unsafe { mem::transmute(storage) };

                    try!(f(&mut storage));
                    Ok(storage)
                }

                #[inline]
                fn get_elements_size() -> usize {
                    use std::mem;

                    let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 0usize)) };
                    mem::size_of_val(fake_ptr)
                }

                #[inline]
                fn to_void_ptr(&self) -> *const () {
                    use std::mem;
                    let (ptr, _): (*const (), usize) = unsafe { mem::transmute(self) };
                    ptr
                }

                #[inline]
                fn ref_from_ptr(ptr: *mut (), size: usize) -> Option<*mut $struct_name<$($gs)*>> {
                    use std::mem;

                    let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 0usize)) };
                    let min_size = mem::size_of_val(fake_ptr);

                    let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 1usize)) };
                    let step = mem::size_of_val(fake_ptr) - min_size;

                    if size < min_size {
                        return None;
                    }

                    let variadic = size - min_size;
                    if variadic % step != 0 {
                        return None;
                    }

                    Some(unsafe { mem::transmute((ptr, (variadic / step) as usize)) })
                }

                #[inline]
                fn is_size_suitable(size: usize) -> bool {
                    use std::mem;

                    let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 0usize)) };
                    let min_size = mem::size_of_val(fake_ptr);

                    let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 1usize)) };
                    let step = mem::size_of_val(fake_ptr) - min_size;

                    size > min_size && (size - min_size) % step == 0
                }
            }
        }
    };

    ($struct_name:ident,) => (
        implement_buffer_content!($struct_name);
    );

    ($struct_name:ident) => (
        implement_buffer_content!(__impl $struct_name []);
    );

    ($struct_name:ident <$t1:tt>) => (
        implement_buffer_content!(__impl $struct_name [$t1]);
    );
}

Implements the glium::buffer::Content trait for the given type.

Contrary to the other similar macros, this one doesn't require you pass the list of parameters.

Only use this macro on structs. Using it with anything else will result in a segfault.

Example

struct Data {
    data: [u32]
}

implement_buffer_content!(Data);