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 an autoincrement column has reached its maximum value.
13    #[error("Autoincrement overflow: {0} column has reached its maximum value")]
14    AutoincrementOverflow(String),
15    /// Error when a constraint prevents the requested operation.
16    #[error("Constraint violation: {0}")]
17    ConstraintViolation(String),
18    /// Error when the data to be written is too large for the page.
19    #[error("Data too large for page (page size: {page_size}, requested: {requested})")]
20    DataTooLarge { page_size: u64, requested: u64 },
21    /// Error when failing to decode data from bytes.
22    #[error("Failed to decode data from bytes: {0}")]
23    DecodeError(DecodeError),
24    /// Error when failing to allocate a new page.
25    #[error("Failed to allocate a new page")]
26    FailedToAllocatePage,
27    /// Error when no index exists for the requested columns.
28    #[error("Index not found for columns: {0:?}")]
29    IndexNotFound(Vec<String>),
30    /// Error when an index entry cannot be located.
31    #[error("Entry not found in index")]
32    EntryNotFound,
33    /// Error when a single key cannot fit into a node page.
34    #[error("Key too large: {size} bytes exceeds maximum {max} bytes")]
35    KeyTooLarge { size: u64, max: u64 },
36    #[error("Offset {offset} is not aligned to {alignment} bytes")]
37    OffsetNotAligned { offset: PageOffset, alignment: u16 },
38    /// Error when attempting to access stable memory out of bounds.
39    #[error("Stable memory access out of bounds")]
40    OutOfBounds,
41    /// Error when attempting to write out of the allocated page.
42    #[error(
43        "Tried to read or write out of the allocated page (page: {page}, offset: {offset}, data size: {data_size}, page size: {page_size})"
44    )]
45    SegmentationFault {
46        page: Page,
47        offset: PageOffset,
48        data_size: u64,
49        page_size: u64,
50    },
51    /// Error from the underlying memory provider.
52    #[error("Memory provider error: {0}")]
53    ProviderError(String),
54}
55
56impl From<TryFromSliceError> for MemoryError {
57    fn from(err: TryFromSliceError) -> Self {
58        MemoryError::DecodeError(DecodeError::from(err))
59    }
60}
61
62impl From<std::string::FromUtf8Error> for MemoryError {
63    fn from(err: std::string::FromUtf8Error) -> Self {
64        MemoryError::DecodeError(DecodeError::from(err))
65    }
66}
67
68impl From<uuid::Error> for MemoryError {
69    fn from(err: uuid::Error) -> Self {
70        MemoryError::DecodeError(DecodeError::from(err))
71    }
72}
73
74/// An enum representing possible decoding errors.
75#[cfg_attr(feature = "candid", derive(candid::CandidType))]
76#[derive(Debug, Error, Deserialize, Serialize)]
77pub enum DecodeError {
78    /// Error when the raw record header is invalid.
79    #[error("Bad raw record header")]
80    BadRawRecordHeader,
81    /// Error when JSON is invalid.
82    #[error("Invalid JSON: {0}")]
83    InvalidJson(String),
84    /// Identity decoding error.
85    #[error("Identity decode error: {0}")]
86    IdentityDecodeError(String),
87    /// Error when failing to convert from slice.
88    #[error("Failed to convert from slice: {0}")]
89    TryFromSliceError(String),
90    /// Error when failing to convert from UTF-8 string.
91    #[error("Failed to convert from UTF-8 string: {0}")]
92    Utf8Error(String),
93    /// Error when the data is too short to decode.
94    #[error("Data too short to decode")]
95    TooShort,
96    /// Error when an invalid discriminant byte is encountered.
97    #[error("Invalid discriminant: {0}")]
98    InvalidDiscriminant(u8),
99    /// UUID error
100    #[error("UUID error: {0}")]
101    UuidError(String),
102}
103
104impl From<uuid::Error> for DecodeError {
105    fn from(err: uuid::Error) -> Self {
106        DecodeError::UuidError(err.to_string())
107    }
108}
109
110impl From<std::string::FromUtf8Error> for DecodeError {
111    fn from(err: std::string::FromUtf8Error) -> Self {
112        DecodeError::Utf8Error(err.to_string())
113    }
114}
115
116impl From<TryFromSliceError> for DecodeError {
117    fn from(err: TryFromSliceError) -> Self {
118        DecodeError::TryFromSliceError(err.to_string())
119    }
120}
121
122#[cfg(feature = "candid")]
123impl From<candid::types::principal::PrincipalError> for DecodeError {
124    fn from(err: candid::types::principal::PrincipalError) -> Self {
125        DecodeError::IdentityDecodeError(err.to_string())
126    }
127}
128
129#[cfg(test)]
130mod tests {
131
132    use super::*;
133
134    #[test]
135    fn test_memory_error_display() {
136        let error = MemoryError::DataTooLarge {
137            page_size: 1024,
138            requested: 2048,
139        };
140        assert_eq!(
141            format!("{}", error),
142            "Data too large for page (page size: 1024, requested: 2048)"
143        );
144    }
145
146    #[test]
147    fn test_decode_error_display() {
148        let error = DecodeError::BadRawRecordHeader;
149        assert_eq!(format!("{}", error), "Bad raw record header");
150    }
151}