use std::{ fmt, ops::{Add, Sub}, }; const WASM_PAGE_SIZE: usize = 65_536; const WASM_MAX_PAGES: usize = 65_536; /// Units of WebAssembly pages (as specified to be 65,536 bytes). #[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Pages(pub u32); impl Pages { pub fn checked_add(self, rhs: Pages) -> Option { let added = (self.0 as usize) + (rhs.0 as usize); if added <= WASM_MAX_PAGES { Some(Pages(added as u32)) } else { None } } pub fn bytes(self) -> Bytes { self.into() } } impl fmt::Debug for Pages { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} pages", self.0) } } /// Units of WebAssembly memory in terms of 8-bit bytes. #[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Bytes(pub usize); impl fmt::Debug for Bytes { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} bytes", self.0) } } impl From for Bytes { fn from(pages: Pages) -> Bytes { Bytes((pages.0 as usize) * WASM_PAGE_SIZE) } } impl Sub for Pages where T: Into, { type Output = Pages; fn sub(self, rhs: T) -> Pages { Pages(self.0 - rhs.into().0) } } impl Add for Pages where T: Into, { type Output = Pages; fn add(self, rhs: T) -> Pages { Pages(self.0 + rhs.into().0) } } impl From for Pages { fn from(bytes: Bytes) -> Pages { Pages((bytes.0 / WASM_PAGE_SIZE) as u32) } } impl Sub for Bytes where T: Into, { type Output = Bytes; fn sub(self, rhs: T) -> Bytes { Bytes(self.0 - rhs.into().0) } } impl Add for Bytes where T: Into, { type Output = Bytes; fn add(self, rhs: T) -> Bytes { Bytes(self.0 + rhs.into().0) } }