blaze-rs 1.0.3

A Rustified OpenCL Experience
Documentation
use std::ops::*;
use crate::prelude::*;
use super::{RawBuffer};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BufferRange {
    pub offset: usize,
    pub cb: usize
}

impl BufferRange {
    #[inline(always)]
    pub const fn new (offset: usize, cb: usize) -> Self {
        Self { offset, cb }
    }

    #[inline]
    pub fn from_parts<T> (offset: usize, size: usize) -> Result<Self> {
        let offset = match offset.checked_mul(core::mem::size_of::<T>()) {
            Some(x) => x,
            None => return Err(Error::new(ErrorKind::InvalidBufferSize, "overflow calculating range offset"))
        };

        let size = match size.checked_mul(core::mem::size_of::<T>()) {
            Some(x) => x,
            None => return Err(Error::new(ErrorKind::InvalidBufferSize, "overflow calculating range size"))
        };

        Ok(Self::new(offset, size))
    }

    #[inline(always)]
    pub fn from_byte_range<R: RangeBounds<usize>> (range: R, max_size: usize) -> Result<Self> {
        Self::from_range::<u8, R>(range, max_size)
    }

    #[inline]
    pub fn from_range<T, R: RangeBounds<usize>> (range: R, max_size: usize) -> Result<Self> {
        macro_rules! _tri_ {
            ($e:expr, $desc:expr) => {
                $e.ok_or_else(|| Error::new(ErrorKind::InvalidBufferSize, $desc))?
            };
        }

        let offset = match range.start_bound() {
            Bound::Excluded(x) => _tri_!(_tri_!(x.checked_add(1), "overflow calculating range offset").checked_mul(core::mem::size_of::<T>()), "overflow calculating range offset"),
            Bound::Included(x) => _tri_!(x.checked_mul(core::mem::size_of::<T>()), "overflow calculating range offset"),
            Bound::Unbounded => 0
        };

        let size = match range.end_bound() {
            Bound::Excluded(x) => _tri_!(x.checked_mul(core::mem::size_of::<T>()), "overflow calculating range size"),
            Bound::Included(x) => _tri_!(_tri_!(x.checked_add(1), "overflow calculating range size").checked_mul(core::mem::size_of::<T>()), "overflow calculating range offset"),
            Bound::Unbounded => max_size
        } - offset;

        return Ok(Self::new(offset, size))
    }
}

pub trait IntoRange {
    fn into_range<T> (self, buf: &RawBuffer) -> Result<BufferRange>;
}

impl IntoRange for BufferRange {
    #[inline(always)]
    fn into_range<T> (self, _buf: &RawBuffer) -> Result<BufferRange> {
        Ok(self)
    }
}

impl IntoRange for Range<usize> {
    #[inline(always)]
    fn into_range<T> (self, buf: &RawBuffer) -> Result<BufferRange> {
        BufferRange::from_range::<T, Self>(self, buf.size()?)
    }
}

impl IntoRange for RangeFrom<usize> {
    #[inline(always)]
    fn into_range<T> (self, buf: &RawBuffer) -> Result<BufferRange> {
        BufferRange::from_range::<T, Self>(self, buf.size()?)
    }
}

impl IntoRange for RangeFull {
    #[inline(always)]
    fn into_range<T> (self, buf: &RawBuffer) -> Result<BufferRange> {
        BufferRange::from_range::<T, Self>(self, buf.size()?)
    }
}

impl IntoRange for RangeInclusive<usize> {
    #[inline(always)]
    fn into_range<T> (self, buf: &RawBuffer) -> Result<BufferRange> {
        BufferRange::from_range::<T, Self>(self, buf.size()?)
    }
}

impl IntoRange for RangeTo<usize> {
    #[inline(always)]
    fn into_range<T> (self, buf: &RawBuffer) -> Result<BufferRange> {
        BufferRange::from_range::<T, Self>(self, buf.size()?)
    }
}

impl IntoRange for RangeToInclusive<usize> {
    #[inline(always)]
    fn into_range<T> (self, buf: &RawBuffer) -> Result<BufferRange> {
        BufferRange::from_range::<T, Self>(self, buf.size()?)
    }
}

impl IntoRange for [usize; 2] {
    #[inline(always)]
    fn into_range<T> (self, _buf: &RawBuffer) -> Result<BufferRange> {
        BufferRange::from_parts::<T>(self[0], self[1])
    }
}

impl IntoRange for (usize, usize) {
    #[inline(always)]
    fn into_range<T> (self, _buf: &RawBuffer) -> Result<BufferRange> {
        BufferRange::from_parts::<T>(self.0, self.1)
    }
}