1use codec::{ConstEncodedLen, Decode, Encode, MaxEncodedLen};
2use jam_types::SEGMENT_LEN;
3
4pub const PAGE_SIZE: u32 = 4096;
6
7pub(crate) const MIN_PAGE: u32 = 16;
8pub(crate) const MAX_PAGE: u32 = u32::MAX / PAGE_SIZE;
9
10#[derive(
12 Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Encode, Decode, MaxEncodedLen,
13)]
14pub struct PageNum(pub u32);
15
16impl PageNum {
17 pub const fn from_address(address: u32) -> Self {
18 Self(address / PAGE_SIZE)
19 }
20
21 pub const fn address(self) -> u32 {
22 self.0 * PAGE_SIZE
23 }
24}
25
26impl core::fmt::Debug for PageNum {
27 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
28 let page = self.0;
29 let address = page.saturating_mul(PAGE_SIZE);
30 let comment = if (MIN_PAGE..=MAX_PAGE).contains(&page) { "" } else { " (invalid!)" };
31 write!(f, "{page}/{address:#x}{comment}")
32 }
33}
34
35impl core::fmt::Display for PageNum {
36 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37 core::fmt::Debug::fmt(self, f)
38 }
39}
40
41impl ConstEncodedLen for PageNum {}
42
43pub trait PageSegmentOps {
51 fn page(&self) -> &[u8; PAGE_SIZE as usize];
53
54 fn page_mut(&mut self) -> &mut [u8; PAGE_SIZE as usize];
56
57 fn page_number(&self) -> PageNum;
59
60 fn set_page_number(&mut self, page: PageNum);
62}
63
64impl PageSegmentOps for [u8; SEGMENT_LEN] {
65 fn page(&self) -> &[u8; PAGE_SIZE as usize] {
66 (&self[..PAGE_SIZE as usize])
67 .try_into()
68 .expect("Slice and array have the same length")
69 }
70
71 fn page_mut(&mut self) -> &mut [u8; PAGE_SIZE as usize] {
72 (&mut self[..PAGE_SIZE as usize])
73 .try_into()
74 .expect("Slice and array have the same length")
75 }
76
77 fn page_number(&self) -> PageNum {
78 let a = &self[PAGE_SIZE as usize..];
79 let page = u32::from_le_bytes([a[0], a[1], a[2], a[3]]);
80 PageNum(page)
81 }
82
83 fn set_page_number(&mut self, page: PageNum) {
84 self[PAGE_SIZE as usize..][..4].copy_from_slice(&page.0.to_le_bytes()[..]);
85 }
86}