use crate::{pin::HostPin, Num, TensorMapTrait};
use std::fmt;
use std::marker::PhantomData;
pub struct HostView<'a, T> {
pin: Option<HostPin<'a>>,
shape: Vec<usize>,
byte_size_override: Option<usize>,
writable: bool,
_marker: PhantomData<T>,
}
impl<'a, T> HostView<'a, T>
where
T: Num + Clone + fmt::Debug,
{
#[allow(dead_code)] pub(crate) fn new(
pin: HostPin<'a>,
shape: Vec<usize>,
byte_size_override: Option<usize>,
access: crate::CpuAccess,
) -> Self {
HostView {
pin: Some(pin),
shape,
byte_size_override,
writable: access.writes(),
_marker: PhantomData,
}
}
fn len_elems(&self) -> usize {
let Some(pin) = self.pin.as_ref() else {
return 0;
};
let elem = std::mem::size_of::<T>();
if elem == 0 {
return 0;
}
let requested = match self.byte_size_override {
Some(bytes) => bytes / elem,
None => self.shape.iter().product::<usize>(),
};
requested.min(pin.len() / elem)
}
#[cfg(feature = "static")]
pub(crate) fn into_bytes(self) -> HostView<'a, u8> {
let elem = std::mem::size_of::<T>().max(1);
let requested_bytes = match self.byte_size_override {
Some(bytes) => bytes,
None => self.shape.iter().product::<usize>() * elem,
};
let byte_len = match self.pin.as_ref() {
Some(pin) => requested_bytes.min(pin.len()),
None => 0,
};
HostView {
pin: self.pin,
shape: vec![byte_len],
byte_size_override: None,
writable: self.writable,
_marker: PhantomData,
}
}
}
impl<T> TensorMapTrait<T> for HostView<'_, T>
where
T: Num + Clone + fmt::Debug,
{
fn shape(&self) -> &[usize] {
&self.shape
}
fn unmap(&mut self) {
self.pin = None;
}
fn is_writable(&self) -> bool {
self.writable
}
fn as_slice(&self) -> &[T] {
let Some(pin) = self.pin.as_ref() else {
return &[];
};
let len = self.len_elems();
if len == 0 {
return &[];
}
unsafe { std::slice::from_raw_parts(pin.as_ptr() as *const T, len) }
}
fn as_mut_slice(&mut self) -> &mut [T] {
crate::assert_map_writable(self.writable, "HostView");
let len = self.len_elems();
let Some(pin) = self.pin.as_ref() else {
return &mut [];
};
if len == 0 {
return &mut [];
}
unsafe { std::slice::from_raw_parts_mut(pin.as_mut_ptr() as *mut T, len) }
}
}
impl<T> std::ops::Deref for HostView<'_, T>
where
T: Num + Clone + fmt::Debug,
{
type Target = [T];
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> std::ops::DerefMut for HostView<'_, T>
where
T: Num + Clone + fmt::Debug,
{
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T> fmt::Debug for HostView<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HostView")
.field("mapped", &self.pin.is_some())
.field("shape", &self.shape)
.field("byte_size_override", &self.byte_size_override)
.field("writable", &self.writable)
.finish()
}
}