pub trait TensorTrait<T>: Send + Sync{
Show 19 methods
// Required methods
fn new(shape: &[usize], name: Option<&str>) -> Result<Self>
where Self: Sized;
fn from_fd(fd: OwnedFd, shape: &[usize], name: Option<&str>) -> Result<Self>
where Self: Sized;
fn clone_fd(&self) -> Result<OwnedFd>;
fn memory(&self) -> TensorMemory;
fn name(&self) -> String;
fn shape(&self) -> &[usize];
fn reshape(&mut self, shape: &[usize]) -> Result<()>;
fn map_with(&self, access: CpuAccess) -> Result<TensorMap<T>>;
fn buffer_identity(&self) -> &BufferIdentity;
// Provided methods
fn len(&self) -> usize { ... }
fn is_empty(&self) -> bool { ... }
fn size(&self) -> usize { ... }
fn capacity_bytes(&self) -> usize { ... }
fn set_logical_shape(&mut self, shape: &[usize]) -> Result<()> { ... }
fn map(&self) -> Result<TensorMap<T>> { ... }
fn map_read(&self) -> Result<TensorMap<T>> { ... }
fn map_write(&self) -> Result<TensorMap<T>> { ... }
fn map_mut(&self) -> Result<TensorMap<T>> { ... }
fn view(&self, offset_bytes: usize, shape: &[usize]) -> Result<Self>
where Self: Sized { ... }
}Expand description
The operations every memory backend implements.
This is the seam that lets Tensor<T> hide which backend is in play.
The implementors are DmaTensor (Linux DMA-BUF), IoSurfaceTensor
(macOS/iOS), AHardwareBufferTensor (Android), ShmTensor, MemTensor,
and PboTensor; TensorStorage<T> dispatches to whichever is active.
Backend types are not public — allocate a Tensor<T> or TensorDyn
and call these methods through it.
Import the trait to get shape, size, map, clone_fd,
buffer_identity, and the zero-copy sub-region view on a tensor value.
Tensor::view and Tensor::batch route through TensorTrait::view, so
each backend’s identity-sharing rule lives in exactly one place.
Required Methods§
Sourcefn new(shape: &[usize], name: Option<&str>) -> Result<Self>where
Self: Sized,
fn new(shape: &[usize], name: Option<&str>) -> Result<Self>where
Self: Sized,
Create a new tensor with the given shape and optional name. If no name is given, a random name will be generated.
Sourcefn from_fd(fd: OwnedFd, shape: &[usize], name: Option<&str>) -> Result<Self>where
Self: Sized,
fn from_fd(fd: OwnedFd, shape: &[usize], name: Option<&str>) -> Result<Self>where
Self: Sized,
Import an existing buffer as a tensor, taking ownership of its file descriptor. The buffer is adopted in place — no bytes are copied.
The backend is detected, not chosen: the fd already belongs to a
buffer type, and this call’s job is to recognize which. On Linux that
is decided by the fd’s filesystem magic, which is stable UAPI
(include/uapi/linux/magic.h):
| Filesystem | Magic | Resulting TensorMemory |
|---|---|---|
dma_buf | DMA_BUF_MAGIC (0x444d4142) | TensorMemory::Dma |
tmpfs (/dev/shm and memfd) | TMPFS_MAGIC (0x01021994) | TensorMemory::Shm |
| anything else | — | rejected — see Errors |
Both supported types are identified positively. An unrecognized filesystem is an error, never a fallback to shared memory: the wrong branch does not fail loudly (a DMA-BUF is mmap-able, so it would import as a perfectly functional tensor that merely isn’t DMA, and a pipe would import as a zero-length one), so guessing would trade a clear error here for silent loss of zero-copy far downstream.
The device number is deliberately not consulted. dma_buf files
live on an internal kernel mount whose st_dev comes from
get_anon_bdev() — an IDA shared with every other anonymous
pseudo-filesystem and allocated in boot order — so the minor a
DMA-BUF lands on varies by kernel build and is not part of any ABI.
On non-Linux Unix (macOS/iOS/Android) there is no fd-based DMA import;
the fd is always adopted as TensorMemory::Shm.
§Arguments
fd- Owned descriptor for the buffer to import. Ownership transfers to the returned tensor and the fd is closed on drop; passclone_fdoutput to keep your own handle.shape- Logical shape to interpret the buffer with. Must describe no more elements than the buffer holds.name- Optional name; a random one is generated whenNone.
§Returns
A tensor sharing the imported buffer’s memory, whose
memory() reports the detected backend.
§Errors
Error::UnknownBufferType- the fd is on a filesystem that is neitherdma_bufnortmpfs, so its buffer type cannot be determined. Carries the observedfstatfsmagic as au32, normalized so it can be looked up inmagic.hdirectly on both 32- and 64-bit targets. Typical causes: a regular file, a pipe or socket, or aMFD_HUGETLBmemfd (hugetlbfs, not tmpfs). Linux only.Error::UnknownDeviceType- the fd’sst_devmajor is non-zero, i.e. it lives on a real block device rather than an anonymous or in-memory filesystem. Linux only.Error::InvalidSize-shapeis empty or describes zero elements.Error::NixError-fstat,fstatfs, ormmapfailed on the descriptor.
§Examples
use edgefirst_tensor::{Tensor, TensorMemory, TensorTrait};
let src = Tensor::<u8>::new(&[480, 640, 3], Some(TensorMemory::Dma), None)?;
// Round-tripping a DMA-BUF fd preserves the backend — the import is
// still zero-copy, and still eligible for GPU/NPU paths.
let imported = Tensor::<u8>::from_fd(src.clone_fd()?, src.shape(), None)?;
assert_eq!(imported.memory(), TensorMemory::Dma);Sourcefn memory(&self) -> TensorMemory
fn memory(&self) -> TensorMemory
Get the memory type of this tensor.
Sourcefn reshape(&mut self, shape: &[usize]) -> Result<()>
fn reshape(&mut self, shape: &[usize]) -> Result<()>
Reshape this tensor to the given shape. The total number of elements must remain the same.
Sourcefn map_with(&self, access: CpuAccess) -> Result<TensorMap<T>>
fn map_with(&self, access: CpuAccess) -> Result<TensorMap<T>>
Map the tensor into memory with the given access direction and return a TensorMap for accessing the data.
access selects the platform mapping mode (read-only IOSurface
lock, dma-buf sync direction, AHardwareBuffer lock usage) and the
map’s mutability: a map obtained with CpuAccess::Read rejects
as_mut_slice. CpuAccess::None is not a mappable direction
and returns Error::InvalidArgument.
Sourcefn buffer_identity(&self) -> &BufferIdentity
fn buffer_identity(&self) -> &BufferIdentity
Get the buffer identity for cache keying and liveness tracking.
Provided Methods§
Sourcefn capacity_bytes(&self) -> usize
fn capacity_bytes(&self) -> usize
Bytes of the underlying allocation (>= the current logical size()).
Defaults to the logical size for storages without spare capacity.
Sourcefn set_logical_shape(&mut self, shape: &[usize]) -> Result<()>
fn set_logical_shape(&mut self, shape: &[usize]) -> Result<()>
Set the logical shape to any shape whose byte size fits the allocation
capacity, without the equal-size constraint of reshape.
Sourcefn map(&self) -> Result<TensorMap<T>>
fn map(&self) -> Result<TensorMap<T>>
Map the tensor read-write (equivalent to
map_with(CpuAccess::ReadWrite) — the historical map()
behavior).
Sourcefn map_read(&self) -> Result<TensorMap<T>>
fn map_read(&self) -> Result<TensorMap<T>>
Map the tensor for CPU reading only. The returned map rejects
as_mut_slice; on macOS this takes the read-only IOSurface lock
(skips the unlock flush), on Linux the dma-buf read-direction
sync.
Sourcefn map_write(&self) -> Result<TensorMap<T>>
fn map_write(&self) -> Result<TensorMap<T>>
Map the tensor for CPU writing (fill-only: reading through a write map may see write-combined memory — do not read the slice).
Sourcefn map_mut(&self) -> Result<TensorMap<T>>
fn map_mut(&self) -> Result<TensorMap<T>>
Map the tensor read-write (alias of map with the
intent spelled out).
Sourcefn view(&self, offset_bytes: usize, shape: &[usize]) -> Result<Self>where
Self: Sized,
fn view(&self, offset_bytes: usize, shape: &[usize]) -> Result<Self>where
Self: Sized,
Create a zero-copy sub-region view of this backing that shares the
underlying allocation and BufferIdentity.
The window is [offset_bytes, offset_bytes + shape.product() * size_of::<T>()) measured from this tensor’s own logical start, so a
sub-view of a sub-view composes by adding offsets. Sharing the parent’s
identity is the contract that lets identity-keyed caches (e.g. the GL
EGLImage import cache) treat offset-distinct windows as one buffer rather
than unrelated allocations — view must never mint a fresh identity.
Defaults to Error::NotImplemented; every backend that supports
sub-views overrides it (Mem, Shm, Linux DMA, macOS IOSurface, Pbo).
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".