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