test_bd/position.rs
1use std::fmt;
2use std::ops::AddAssign;
3use std::ops::Sub;
4
5use serde::Deserialize;
6use serde::Serialize;
7
8/// A position index representing an 8-byte aligned offset in a block device.
9///
10/// `IndexPos` is a type-safe wrapper around a `u64` that represents positions
11/// in units of 8 bytes. This is used throughout the library to ensure proper
12/// alignment and avoid confusion between byte offsets and index positions.
13///
14/// # Examples
15///
16/// ```
17/// use test_bd::IndexPos;
18///
19/// // Create a position at index 100 (which is byte offset 800)
20/// let pos = IndexPos::new(100);
21/// assert_eq!(pos.as_u64(), 100);
22/// assert_eq!(pos.as_abs_byte_offset(), 800);
23/// ```
24#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
25#[repr(transparent)]
26pub struct IndexPos(u64);
27
28impl IndexPos {
29 /// Creates a new `IndexPos` from an index value.
30 ///
31 /// # Arguments
32 ///
33 /// * `idx` - The index value (in units of 8 bytes)
34 ///
35 /// # Examples
36 ///
37 /// ```
38 /// use test_bd::IndexPos;
39 ///
40 /// let pos = IndexPos::new(42);
41 /// assert_eq!(pos.as_u64(), 42);
42 /// ```
43 pub const fn new(idx: u64) -> Self {
44 IndexPos(idx)
45 }
46
47 /// Returns the raw index value as a `u64`.
48 ///
49 /// # Examples
50 ///
51 /// ```
52 /// use test_bd::IndexPos;
53 ///
54 /// let pos = IndexPos::new(100);
55 /// assert_eq!(pos.as_u64(), 100);
56 /// ```
57 pub const fn as_u64(self) -> u64 {
58 self.0
59 }
60
61 /// Converts the index position to an absolute byte offset.
62 ///
63 /// Since each index represents 8 bytes, this returns `index * 8`.
64 /// However, this could change, so use this method.
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// use test_bd::IndexPos;
70 ///
71 /// let pos = IndexPos::new(100);
72 /// assert_eq!(pos.as_abs_byte_offset(), 800);
73 /// ```
74 pub const fn as_abs_byte_offset(self) -> u64 {
75 self.0 * 8
76 }
77}
78
79impl fmt::Display for IndexPos {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 write!(f, "IndexPos({})", self.0)
82 }
83}
84
85impl AddAssign for IndexPos {
86 fn add_assign(&mut self, other: Self) {
87 self.0 += other.0;
88 }
89}
90
91impl Sub for IndexPos {
92 type Output = u64;
93
94 fn sub(self, rhs: IndexPos) -> Self::Output {
95 self.0 - rhs.0
96 }
97}