Skip to main content

dynamo_memory/
offset.rs

1// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use super::{
5    Any, Buffer, MemoryDescription, Result, StorageError, StorageKind, nixl::NixlDescriptor,
6};
7
8/// An [`OffsetBuffer`] is a new [`Buffer`]-like object that represents a sub-region (still contiguous)
9/// within an existing [`Buffer`].
10#[derive(Clone)]
11pub struct OffsetBuffer {
12    base: Buffer,
13    offset: usize,
14    size: usize,
15}
16
17impl std::fmt::Debug for OffsetBuffer {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        f.debug_struct("OffsetBuffer")
20            .field("base", &self.base)
21            .field("offset", &self.offset)
22            .field("size", &self.size)
23            .finish()
24    }
25}
26
27impl OffsetBuffer {
28    /// Create a new offset view into an existing memory region.
29    ///
30    /// Returns an error if the offset and length exceed the bounds of the base region.
31    pub fn new(base: Buffer, offset: usize, size: usize) -> Result<Self> {
32        let end = offset
33            .checked_add(size)
34            .ok_or_else(|| StorageError::Unsupported("offset overflow".into()))?;
35        if end > base.size() {
36            return Err(StorageError::Unsupported(
37                "offset region exceeds base allocation bounds".into(),
38            ));
39        }
40        Ok(Self { base, offset, size })
41    }
42
43    /// Get the offset relative to the base mapping.
44    pub fn offset(&self) -> usize {
45        self.offset
46    }
47
48    /// Access the underlying base region.
49    pub fn base(&self) -> &Buffer {
50        &self.base
51    }
52}
53
54impl MemoryDescription for OffsetBuffer {
55    fn addr(&self) -> usize {
56        self.base.addr() + self.offset
57    }
58
59    fn size(&self) -> usize {
60        self.size
61    }
62
63    fn storage_kind(&self) -> StorageKind {
64        self.base.storage_kind()
65    }
66
67    fn as_any(&self) -> &dyn Any {
68        self
69    }
70
71    fn nixl_descriptor(&self) -> Option<NixlDescriptor> {
72        let mut descriptor = self.base.nixl_descriptor()?;
73        descriptor.addr = self.addr() as u64;
74        descriptor.size = self.size();
75        Some(descriptor)
76    }
77}