use crate::{
frontend::container::{buffer_len::expand_buffer_length_native, slice},
prelude::*,
unexpanded,
};
use core::marker::PhantomData;
use cubecl_runtime::server::Handle;
use serde::{Deserialize, Serialize};
pub struct Peer<T: ?Sized> {
_buffer: PhantomData<T>,
}
impl<C: CubePrimitive> CubeType for Peer<[C]> {
type ExpandType = SliceExpand<C>;
}
impl<C: CubePrimitive> core::ops::Deref for Peer<[C]> {
type Target = [C];
fn deref(&self) -> &[C] {
unexpanded!()
}
}
impl<C: CubePrimitive> core::ops::DerefMut for Peer<[C]> {
fn deref_mut(&mut self) -> &mut [C] {
unexpanded!()
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct PeerCompilationArg;
pub struct PeerArg {
pub(crate) handle: BufferBinding,
}
impl PeerArg {
pub unsafe fn from_raw_parts(handle: &Handle, length: usize) -> Self {
assert!(
handle.peer.is_some(),
"a `Peer` parameter takes a handle shared with `share_with_peers`"
);
Self {
handle: unsafe { BufferBinding::from_raw_parts(handle.clone(), length) },
}
}
}
impl<C: CubePrimitive> LaunchArg for Peer<[C]> {
type RuntimeArg = PeerArg;
type CompilationArg = PeerCompilationArg;
fn register(arg: Self::RuntimeArg, launcher: &mut KernelLauncher) -> Self::CompilationArg {
let elem_size = launcher.with_scope(|scope| C::__expand_size(scope));
launcher.register_peer(arg, elem_size);
PeerCompilationArg
}
fn expand(_arg: &Self::CompilationArg, builder: &mut KernelBuilder) -> SliceExpand<C> {
let buffer = builder.peer_buffer(C::__expand_as_type(&builder.scope));
let scope = &builder.scope;
let len = expand_buffer_length_native(scope, buffer);
let slice_var =
slice::from_raw_parts::<C>(scope, buffer, 0usize.into_expand(scope), len.into());
slice_var.expand.into()
}
}