Skip to main content

ic_dbms_api/memory/
error.rs

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