1use super::*;
7use std::fmt::{self, Display, Formatter};
8use std::ops::{Add, AddAssign, Sub, SubAssign};
9
10#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
12pub(super) struct GuestOffset(pub u64);
13
14#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
16pub(super) struct GuestCluster(pub u64);
17
18#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
20pub(super) struct HostOffset(pub u64);
21
22#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
24pub(super) struct HostCluster(pub u64);
25
26#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
28pub(super) struct ClusterCount(pub u64);
29
30impl GuestOffset {
31 pub fn in_cluster_offset(self, cluster_bits: u32) -> usize {
33 (self.0 % (1 << cluster_bits)) as usize
34 }
35
36 pub fn l2_index(self, cluster_bits: u32) -> usize {
38 self.cluster(cluster_bits).l2_index(cluster_bits)
39 }
40
41 pub fn l1_index(self, cluster_bits: u32) -> usize {
43 self.cluster(cluster_bits).l1_index(cluster_bits)
44 }
45
46 pub fn cluster(self, cluster_bits: u32) -> GuestCluster {
48 GuestCluster(self.0 >> cluster_bits)
49 }
50
51 pub fn checked_cluster(self, cluster_bits: u32) -> Option<GuestCluster> {
57 (self.in_cluster_offset(cluster_bits) == 0).then_some(self.cluster(cluster_bits))
58 }
59
60 pub fn remaining_in_cluster(self, cluster_bits: u32) -> u64 {
62 ((1 << cluster_bits) - self.in_cluster_offset(cluster_bits)) as u64
63 }
64
65 pub fn remaining_in_l2_table(self, cluster_bits: u32) -> u64 {
67 let l2_entries = 1 << (cluster_bits - 3);
69 let after_this = ((l2_entries - (self.l2_index(cluster_bits) + 1)) as u64) << cluster_bits;
70 self.remaining_in_cluster(cluster_bits) + after_this
71 }
72}
73
74impl GuestCluster {
75 pub fn offset(self, cluster_bits: u32) -> GuestOffset {
77 GuestOffset(self.0 << cluster_bits)
78 }
79
80 pub fn l2_index(self, cluster_bits: u32) -> usize {
82 let l2_entries = 1 << (cluster_bits - 3);
84 (self.0 % l2_entries) as usize
85 }
86
87 pub fn l1_index(self, cluster_bits: u32) -> usize {
89 let l2_entries_shift = cluster_bits - 3;
90 (self.0 >> l2_entries_shift) as usize
91 }
92
93 pub fn from_l1_l2_indices(l1_index: usize, l2_index: usize, cluster_bits: u32) -> Self {
95 let l2_entries_shift = cluster_bits - 3;
96 GuestCluster(((l1_index as u64) << l2_entries_shift) + l2_index as u64)
97 }
98
99 pub fn next_in_l2(self, cluster_bits: u32) -> Option<GuestCluster> {
103 let l2_entries = 1 << (cluster_bits - 3);
105 let l1_index = self.l1_index(cluster_bits);
106 let l2_index = self.l2_index(cluster_bits);
107 let l2_index = l2_index.checked_add(1)?;
108 if l2_index >= l2_entries {
109 None
110 } else {
111 Some(GuestCluster::from_l1_l2_indices(
112 l1_index,
113 l2_index,
114 cluster_bits,
115 ))
116 }
117 }
118
119 pub fn first_in_next_l2(self, cluster_bits: u32) -> GuestCluster {
121 let l2_entries = 1 << (cluster_bits - 3);
122 GuestCluster((self.0 + 1).next_multiple_of(l2_entries))
123 }
124}
125
126impl HostOffset {
127 pub fn in_cluster_offset(self, cluster_bits: u32) -> usize {
129 (self.0 % (1 << cluster_bits)) as usize
130 }
131
132 pub fn cluster(self, cluster_bits: u32) -> HostCluster {
134 HostCluster(self.0 >> cluster_bits)
135 }
136
137 pub fn checked_cluster(self, cluster_bits: u32) -> Option<HostCluster> {
143 (self.in_cluster_offset(cluster_bits) == 0).then_some(self.cluster(cluster_bits))
144 }
145}
146
147impl HostCluster {
148 pub fn offset(self, cluster_bits: u32) -> HostOffset {
150 HostOffset(self.0 << cluster_bits)
151 }
152
153 pub fn rb_index(self, rb_bits: u32) -> usize {
155 let rb_entries = 1 << rb_bits;
156 (self.0 % rb_entries) as usize
157 }
158
159 pub fn rt_index(self, rb_bits: u32) -> usize {
161 (self.0 >> rb_bits) as usize
162 }
163
164 pub fn rt_rb_indices(self, rb_bits: u32) -> (usize, usize) {
166 (self.rt_index(rb_bits), self.rb_index(rb_bits))
167 }
168
169 pub fn from_ref_indices(rt_index: usize, rb_index: usize, rb_bits: u32) -> Self {
171 HostCluster(((rt_index as u64) << rb_bits) + rb_index as u64)
172 }
173
174 pub fn relative_offset(self, guest_offset: GuestOffset, cluster_bits: u32) -> HostOffset {
181 self.offset(cluster_bits) + guest_offset.in_cluster_offset(cluster_bits) as u64
182 }
183}
184
185impl ClusterCount {
186 pub fn from_byte_size(byte_size: u64, cluster_bits: u32) -> Self {
190 ClusterCount(byte_size.div_ceil(1 << cluster_bits))
191 }
192
193 pub fn checked_from_byte_size(byte_size: u64, cluster_bits: u32) -> Option<Self> {
197 (byte_size & ((1 << cluster_bits) - 1) == 0)
198 .then_some(ClusterCount(byte_size >> cluster_bits))
199 }
200
201 pub fn byte_size(self, cluster_bits: u32) -> u64 {
203 self.0 << cluster_bits
204 }
205}
206
207impl Add<ClusterCount> for GuestCluster {
208 type Output = Self;
209
210 fn add(self, rhs: ClusterCount) -> Self {
211 GuestCluster(self.0 + rhs.0)
212 }
213}
214
215impl AddAssign<ClusterCount> for GuestCluster {
216 fn add_assign(&mut self, rhs: ClusterCount) {
217 self.0 += rhs.0;
218 }
219}
220
221impl Sub<ClusterCount> for GuestCluster {
222 type Output = Self;
223
224 fn sub(self, rhs: ClusterCount) -> Self {
225 GuestCluster(self.0 - rhs.0)
226 }
227}
228
229impl SubAssign<ClusterCount> for GuestCluster {
230 fn sub_assign(&mut self, rhs: ClusterCount) {
231 self.0 -= rhs.0;
232 }
233}
234
235impl Sub<GuestCluster> for GuestCluster {
236 type Output = ClusterCount;
237
238 fn sub(self, rhs: Self) -> ClusterCount {
239 ClusterCount(self.0 - rhs.0)
240 }
241}
242
243impl Add<ClusterCount> for HostCluster {
244 type Output = Self;
245
246 fn add(self, rhs: ClusterCount) -> Self {
247 HostCluster(self.0 + rhs.0)
248 }
249}
250
251impl AddAssign<ClusterCount> for HostCluster {
252 fn add_assign(&mut self, rhs: ClusterCount) {
253 self.0 += rhs.0;
254 }
255}
256
257impl Sub<ClusterCount> for HostCluster {
258 type Output = Self;
259
260 fn sub(self, rhs: ClusterCount) -> Self {
261 HostCluster(self.0 - rhs.0)
262 }
263}
264
265impl SubAssign<ClusterCount> for HostCluster {
266 fn sub_assign(&mut self, rhs: ClusterCount) {
267 self.0 -= rhs.0;
268 }
269}
270
271impl Sub<HostCluster> for HostCluster {
272 type Output = ClusterCount;
273
274 fn sub(self, rhs: Self) -> ClusterCount {
275 ClusterCount(self.0 - rhs.0)
276 }
277}
278
279impl Add<ClusterCount> for ClusterCount {
280 type Output = Self;
281
282 fn add(self, rhs: ClusterCount) -> Self {
283 ClusterCount(self.0 + rhs.0)
284 }
285}
286
287impl AddAssign<ClusterCount> for ClusterCount {
288 fn add_assign(&mut self, rhs: ClusterCount) {
289 self.0 += rhs.0;
290 }
291}
292
293impl Sub<ClusterCount> for ClusterCount {
294 type Output = Self;
295
296 fn sub(self, rhs: ClusterCount) -> Self {
297 ClusterCount(self.0 - rhs.0)
298 }
299}
300
301impl SubAssign<ClusterCount> for ClusterCount {
302 fn sub_assign(&mut self, rhs: ClusterCount) {
303 self.0 -= rhs.0;
304 }
305}
306
307impl Add<u64> for GuestOffset {
308 type Output = Self;
309
310 fn add(self, rhs: u64) -> Self {
311 GuestOffset(self.0 + rhs)
312 }
313}
314
315impl Sub<u64> for GuestOffset {
316 type Output = Self;
317
318 fn sub(self, rhs: u64) -> Self {
319 GuestOffset(self.0 - rhs)
320 }
321}
322
323impl Sub<GuestOffset> for GuestOffset {
324 type Output = u64;
325
326 fn sub(self, rhs: Self) -> u64 {
327 self.0 - rhs.0
328 }
329}
330
331impl Add<u64> for HostOffset {
332 type Output = Self;
333
334 fn add(self, rhs: u64) -> Self {
335 HostOffset(self.0 + rhs)
336 }
337}
338
339impl Sub<u64> for HostOffset {
340 type Output = Self;
341
342 fn sub(self, rhs: u64) -> Self {
343 HostOffset(self.0 - rhs)
344 }
345}
346
347impl Sub<HostOffset> for HostOffset {
348 type Output = u64;
349
350 fn sub(self, rhs: Self) -> u64 {
351 self.0 - rhs.0
352 }
353}
354
355impl Display for GuestOffset {
356 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
357 write!(f, "0x{:x}", self.0)
358 }
359}
360
361impl Display for HostOffset {
362 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
363 write!(f, "0x{:x}", self.0)
364 }
365}
366
367impl Display for ClusterCount {
368 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
369 write!(f, "{}", self.0)
370 }
371}