use crate::array::Array;
use crate::error::Result;
pub fn require<T: Clone>(
array: &Array<T>,
requirements: Option<ArrayRequirements>,
) -> Result<Array<T>> {
let requirements = requirements.unwrap_or(ArrayRequirements::empty());
if requirements.is_empty() {
return Ok(array.clone());
}
let need_c_layout = requirements.contains(ArrayRequirements::C_LAYOUT);
let need_f_layout = requirements.contains(ArrayRequirements::F_LAYOUT);
let need_contiguous = requirements.contains(ArrayRequirements::CONTIGUOUS);
let _need_owner = requirements.contains(ArrayRequirements::OWNDATA);
let _need_writeable = requirements.contains(ArrayRequirements::WRITEABLE);
let meets_c_layout = if need_c_layout {
array.is_c_contiguous()
} else {
true
};
let meets_f_layout = if need_f_layout {
array.is_f_contiguous()
} else {
true
};
let meets_contiguous = if need_contiguous {
array.is_contiguous()
} else {
true
};
if meets_c_layout && meets_f_layout && meets_contiguous {
return Ok(array.clone());
}
let mut result = array.clone();
if need_c_layout && !meets_c_layout {
result = result.to_c_layout();
}
if need_f_layout && !meets_f_layout {
result = result.to_f_layout();
}
if need_contiguous && !meets_contiguous && !need_c_layout && !need_f_layout {
result = result.to_c_layout();
}
Ok(result)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArrayRequirements(u32);
impl ArrayRequirements {
pub const CONTIGUOUS: Self = Self(1 << 0);
pub const C_LAYOUT: Self = Self(1 << 1);
pub const F_LAYOUT: Self = Self(1 << 2);
pub const OWNDATA: Self = Self(1 << 3);
pub const WRITEABLE: Self = Self(1 << 4);
pub fn empty() -> Self {
Self(0)
}
pub fn is_empty(&self) -> bool {
self.0 == 0
}
pub fn contains(&self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
}
impl std::ops::BitOr for ArrayRequirements {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl std::ops::BitAnd for ArrayRequirements {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
}