Skip to main content

nub_host_kvm/mem/
ptr_offset.rs

1/*
2Copyright 2025  The Hyperlight Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
18use std::convert::From;
19use std::ops::{Add, Sub};
20
21use tracing::{Span, instrument};
22
23use crate::Result;
24use crate::error::HyperlightError;
25
26/// An offset into a given address space.
27///
28/// Use this type to distinguish between an offset and a raw pointer
29#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
30pub(crate) struct Offset(u64);
31
32impl Default for Offset {
33    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
34    fn default() -> Self {
35        Offset::from(0_u64)
36    }
37}
38
39impl From<u64> for Offset {
40    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
41    fn from(val: u64) -> Self {
42        Self(val)
43    }
44}
45
46impl From<&Offset> for u64 {
47    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
48    fn from(val: &Offset) -> u64 {
49        val.0
50    }
51}
52
53impl From<Offset> for u64 {
54    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
55    fn from(val: Offset) -> u64 {
56        val.0
57    }
58}
59
60impl TryFrom<Offset> for i64 {
61    type Error = HyperlightError;
62    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
63    fn try_from(val: Offset) -> Result<i64> {
64        Ok(i64::try_from(val.0)?)
65    }
66}
67
68impl TryFrom<i64> for Offset {
69    type Error = HyperlightError;
70    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
71    fn try_from(val: i64) -> Result<Offset> {
72        let val_u64 = u64::try_from(val)?;
73        Ok(Offset::from(val_u64))
74    }
75}
76
77impl TryFrom<usize> for Offset {
78    type Error = HyperlightError;
79    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
80    fn try_from(val: usize) -> Result<Offset> {
81        Ok(u64::try_from(val).map(Offset::from)?)
82    }
83}
84
85/// Convert an `Offset` to a `usize`, returning an `Err` if the
86/// conversion couldn't be made.
87impl TryFrom<&Offset> for usize {
88    type Error = HyperlightError;
89    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
90    fn try_from(val: &Offset) -> Result<usize> {
91        Ok(usize::try_from(val.0)?)
92    }
93}
94
95impl TryFrom<Offset> for usize {
96    type Error = HyperlightError;
97    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
98    fn try_from(val: Offset) -> Result<usize> {
99        usize::try_from(&val)
100    }
101}
102
103impl Add<Offset> for Offset {
104    type Output = Offset;
105    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
106    fn add(self, rhs: Offset) -> Offset {
107        Offset::from(self.0 + rhs.0)
108    }
109}
110
111impl Add<usize> for Offset {
112    type Output = Offset;
113    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
114    fn add(self, rhs: usize) -> Offset {
115        Offset(self.0 + rhs as u64)
116    }
117}
118
119impl Add<Offset> for usize {
120    type Output = Offset;
121    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
122    fn add(self, rhs: Offset) -> Offset {
123        rhs.add(self)
124    }
125}
126
127impl Add<u64> for Offset {
128    type Output = Offset;
129    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
130    fn add(self, rhs: u64) -> Offset {
131        Offset(self.0 + rhs)
132    }
133}
134
135impl Add<Offset> for u64 {
136    type Output = Offset;
137    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
138    fn add(self, rhs: Offset) -> Offset {
139        rhs.add(self)
140    }
141}
142
143impl Sub<Offset> for Offset {
144    type Output = Offset;
145    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
146    fn sub(self, rhs: Offset) -> Offset {
147        Offset::from(self.0 - rhs.0)
148    }
149}
150
151impl Sub<usize> for Offset {
152    type Output = Offset;
153    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
154    fn sub(self, rhs: usize) -> Offset {
155        Offset(self.0 - rhs as u64)
156    }
157}
158
159impl Sub<Offset> for usize {
160    type Output = Offset;
161    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
162    fn sub(self, rhs: Offset) -> Offset {
163        rhs.sub(self)
164    }
165}
166
167impl Sub<u64> for Offset {
168    type Output = Offset;
169    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
170    fn sub(self, rhs: u64) -> Offset {
171        Offset(self.0 - rhs)
172    }
173}
174
175impl Sub<Offset> for u64 {
176    type Output = Offset;
177    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
178    fn sub(self, rhs: Offset) -> Offset {
179        rhs.sub(self)
180    }
181}
182
183impl PartialEq<usize> for Offset {
184    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
185    fn eq(&self, other: &usize) -> bool {
186        match usize::try_from(self) {
187            Ok(offset_usize) => offset_usize == *other,
188            _ => false,
189        }
190    }
191}
192
193impl PartialOrd<usize> for Offset {
194    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
195    fn partial_cmp(&self, rhs: &usize) -> Option<Ordering> {
196        match usize::try_from(self) {
197            Ok(offset_usize) if offset_usize > *rhs => Some(Ordering::Greater),
198            Ok(offset_usize) if offset_usize == *rhs => Some(Ordering::Equal),
199            Ok(_) => Some(Ordering::Less),
200            Err(_) => None,
201        }
202    }
203}
204
205impl PartialEq<u64> for Offset {
206    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
207    fn eq(&self, rhs: &u64) -> bool {
208        u64::from(self) == *rhs
209    }
210}
211
212impl PartialOrd<u64> for Offset {
213    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
214    fn partial_cmp(&self, rhs: &u64) -> Option<Ordering> {
215        let lhs: u64 = self.into();
216        match lhs > *rhs {
217            true => Some(Ordering::Greater),
218            false if lhs == *rhs => Some(Ordering::Equal),
219            false => Some(Ordering::Less),
220        }
221    }
222}