Skip to main content

wasm_dbms_api/memory/
error.rs

1use std::array::TryFromSliceError;
2
3use serde::{Deserialize, Serialize};
4use thiserror::Error;
5
6use crate::memory::{Page, PageOffset};
7
8/// An enum representing possible memory-related errors.
9#[cfg_attr(feature = "candid", derive(candid::CandidType))]
10#[derive(Debug, Error, Deserialize, Serialize)]
11pub enum MemoryError {
12    /// Error when a constraint prevents the requested operation.
13    #[error("Constraint violation: {0}")]
14    ConstraintViolation(String),
15    /// Error when the data to be written is too large for the page.
16    #[error("Data too large for page (page size: {page_size}, requested: {requested})")]
17    DataTooLarge { page_size: u64, requested: u64 },
18    /// Error when failing to decode data from bytes.
19    #[error("Failed to decode data from bytes: {0}")]
20    DecodeError(DecodeError),
21    /// Error when failing to allocate a new page.
22    #[error("Failed to allocate a new page")]
23    FailedToAllocatePage,
24    #[error("Offset {offset} is not aligned to {alignment} bytes")]
25    OffsetNotAligned { offset: PageOffset, alignment: u16 },
26    /// Error when attempting to access stable memory out of bounds.
27    #[error("Stable memory access out of bounds")]
28    OutOfBounds,
29    /// Error when attempting to write out of the allocated page.
30    #[error(
31        "Tried to read or write out of the allocated page (page: {page}, offset: {offset}, data size: {data_size}, page size: {page_size})"
32    )]
33    SegmentationFault {
34        page: Page,
35        offset: PageOffset,
36        data_size: u64,
37        page_size: u64,
38    },
39    /// Error from the underlying memory provider.
40    #[error("Memory provider error: {0}")]
41    ProviderError(String),
42}
43
44impl From<TryFromSliceError> for MemoryError {
45    fn from(err: TryFromSliceError) -> Self {
46        MemoryError::DecodeError(DecodeError::from(err))
47    }
48}
49
50impl From<std::string::FromUtf8Error> for MemoryError {
51    fn from(err: std::string::FromUtf8Error) -> Self {
52        MemoryError::DecodeError(DecodeError::from(err))
53    }
54}
55
56impl From<uuid::Error> for MemoryError {
57    fn from(err: uuid::Error) -> Self {
58        MemoryError::DecodeError(DecodeError::from(err))
59    }
60}
61
62/// An enum representing possible decoding errors.
63#[cfg_attr(feature = "candid", derive(candid::CandidType))]
64#[derive(Debug, Error, Deserialize, Serialize)]
65pub enum DecodeError {
66    /// Error when the raw record header is invalid.
67    #[error("Bad raw record header")]
68    BadRawRecordHeader,
69    /// Error when JSON is invalid.
70    #[error("Invalid JSON: {0}")]
71    InvalidJson(String),
72    /// Identity decoding error.
73    #[error("Identity decode error: {0}")]
74    IdentityDecodeError(String),
75    /// Error when failing to convert from slice.
76    #[error("Failed to convert from slice: {0}")]
77    TryFromSliceError(String),
78    /// Error when failing to convert from UTF-8 string.
79    #[error("Failed to convert from UTF-8 string: {0}")]
80    Utf8Error(String),
81    /// Error when the data is too short to decode.
82    #[error("Data too short to decode")]
83    TooShort,
84    /// UUID error
85    #[error("UUID error: {0}")]
86    UuidError(String),
87}
88
89impl From<uuid::Error> for DecodeError {
90    fn from(err: uuid::Error) -> Self {
91        DecodeError::UuidError(err.to_string())
92    }
93}
94
95impl From<std::string::FromUtf8Error> for DecodeError {
96    fn from(err: std::string::FromUtf8Error) -> Self {
97        DecodeError::Utf8Error(err.to_string())
98    }
99}
100
101impl From<TryFromSliceError> for DecodeError {
102    fn from(err: TryFromSliceError) -> Self {
103        DecodeError::TryFromSliceError(err.to_string())
104    }
105}
106
107#[cfg(feature = "candid")]
108impl From<candid::types::principal::PrincipalError> for DecodeError {
109    fn from(err: candid::types::principal::PrincipalError) -> Self {
110        DecodeError::IdentityDecodeError(err.to_string())
111    }
112}
113
114#[cfg(test)]
115mod tests {
116
117    use super::*;
118
119    #[test]
120    fn test_memory_error_display() {
121        let error = MemoryError::DataTooLarge {
122            page_size: 1024,
123            requested: 2048,
124        };
125        assert_eq!(
126            format!("{}", error),
127            "Data too large for page (page size: 1024, requested: 2048)"
128        );
129    }
130
131    #[test]
132    fn test_decode_error_display() {
133        let error = DecodeError::BadRawRecordHeader;
134        assert_eq!(format!("{}", error), "Bad raw record header");
135    }
136}