use std::any::TypeId;
use crate::{
buffers::{TrajectoryBatch, buffer::TrajectoryView},
error::TensorError,
tensor::R2lTensor,
};
pub struct OwnedView<T: R2lTensor> {
states: Vec<T>,
next_states: Vec<T>,
actions: Vec<T>,
rewards: Vec<f32>,
terminated: Vec<bool>,
truncated: Vec<bool>,
}
impl<T: R2lTensor> OwnedView<T> {
fn new(
states: Vec<T>,
next_states: Vec<T>,
actions: Vec<T>,
rewards: Vec<f32>,
terminated: Vec<bool>,
truncated: Vec<bool>,
) -> Self {
Self {
states,
next_states,
actions,
rewards,
terminated,
truncated,
}
}
}
pub enum TrajectoryViewsWrapper<'a, T: R2lTensor> {
Borrowed(TrajectoryView<'a, T>),
Owned(OwnedView<T>),
}
impl<T: R2lTensor> TrajectoryViewsWrapper<'_, T> {
pub fn from_view<'b, S: R2lTensor>(
view: &'b TrajectoryView<'b, S>,
) -> Result<TrajectoryViewsWrapper<'b, T>, TensorError> {
if TypeId::of::<S>() == TypeId::of::<T>() {
let states = unsafe { &*(std::ptr::from_ref::<[S]>(view.states()) as *const [T]) };
let next_states =
unsafe { &*(std::ptr::from_ref::<[S]>(view.next_states()) as *const [T]) };
let actions = unsafe { &*(std::ptr::from_ref::<[S]>(view.actions()) as *const [T]) };
return Ok(TrajectoryViewsWrapper::Borrowed(TrajectoryView {
states,
next_states,
actions,
rewards: view.rewards(),
terminated: view.terminated(),
truncated: view.truncated(),
}));
}
let states = view
.states()
.iter()
.map(T::convert)
.collect::<Result<Vec<_>, _>>()?;
let next_states = view
.next_states()
.iter()
.map(T::convert)
.collect::<Result<Vec<_>, _>>()?;
let actions = view
.actions()
.iter()
.map(T::convert)
.collect::<Result<Vec<_>, _>>()?;
let rewards = view.rewards().to_vec();
let terminated = view.terminated().to_vec();
let truncated = view.truncated().to_vec();
Ok(TrajectoryViewsWrapper::Owned(OwnedView::new(
states,
next_states,
actions,
rewards,
terminated,
truncated,
)))
}
}
impl<T: R2lTensor> TrajectoryBatch<T> for TrajectoryViewsWrapper<'_, T> {
fn len(&self) -> usize {
match self {
Self::Borrowed(t) => t.len(),
Self::Owned(o) => o.states.len(),
}
}
fn is_empty(&self) -> bool {
match self {
Self::Borrowed(t) => t.is_empty(),
Self::Owned(o) => o.states.is_empty(),
}
}
fn states(&self) -> &[T] {
match self {
Self::Borrowed(t) => t.states(),
Self::Owned(o) => &o.states,
}
}
fn next_states(&self) -> &[T] {
match self {
Self::Borrowed(t) => t.next_states(),
Self::Owned(o) => &o.next_states,
}
}
fn actions(&self) -> &[T] {
match self {
Self::Borrowed(t) => t.actions(),
Self::Owned(o) => &o.actions,
}
}
fn rewards(&self) -> &[f32] {
match self {
Self::Borrowed(t) => t.rewards(),
Self::Owned(o) => &o.rewards,
}
}
fn terminated(&self) -> &[bool] {
match self {
Self::Borrowed(t) => t.terminated(),
Self::Owned(o) => &o.terminated,
}
}
fn truncated(&self) -> &[bool] {
match self {
Self::Borrowed(t) => t.truncated(),
Self::Owned(o) => &o.truncated,
}
}
}