gui_server_api/
error.rs

1// SPDX-FileCopyrightText: 2024 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use server::{AsScalar, FromScalar};
5
6#[derive(Debug, Default, thiserror::Error, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
7pub enum NavigationError {
8    #[default]
9    #[error("Internal error")]
10    InternalError,
11
12    #[error("Request buffer is too small for the response")]
13    RequestBufferTooSmall,
14
15    #[error("An other PID tried to navigate there at the same time (PID={0})")]
16    ConcurrentNavigationRequest(xous::PID),
17
18    #[error("Couldn't find an running app with the given AppId")]
19    AppIdNotFound,
20
21    #[error("No pending navigation request")]
22    NoNavigationRequest,
23
24    #[error("Modal app exited unexpectedly")]
25    ModalExited,
26
27    #[error("The screen is locked")]
28    Locked,
29
30    #[error("The navigation was cancelled by the system")]
31    CanceledBySystem,
32
33    #[error("The navigation was cancelled by the user")]
34    CanceledByUser,
35}
36
37impl AsScalar<3> for NavigationError {
38    fn as_scalar(&self) -> [u32; 3] {
39        match self {
40            NavigationError::InternalError => [1, 0, 0],
41            NavigationError::RequestBufferTooSmall => [2, 0, 0],
42            NavigationError::ConcurrentNavigationRequest(pid) => [3, pid.get() as u32, 0],
43            NavigationError::AppIdNotFound => [4, 0, 0],
44            NavigationError::NoNavigationRequest => [5, 0, 0],
45            NavigationError::ModalExited => [6, 0, 0],
46            NavigationError::Locked => [7, 0, 0],
47            NavigationError::CanceledBySystem => [8, 0, 0],
48            NavigationError::CanceledByUser => [9, 0, 0],
49        }
50    }
51}
52
53impl FromScalar<3> for NavigationError {
54    fn from_scalar([kind, arg, _]: [u32; 3]) -> Self {
55        match kind {
56            1 => NavigationError::InternalError,
57            2 => NavigationError::RequestBufferTooSmall,
58            3 => u8::try_from(arg)
59                .ok()
60                .and_then(xous::PID::new)
61                .map(NavigationError::ConcurrentNavigationRequest)
62                .unwrap_or(NavigationError::InternalError),
63            4 => NavigationError::AppIdNotFound,
64            5 => NavigationError::NoNavigationRequest,
65            6 => NavigationError::ModalExited,
66            7 => NavigationError::Locked,
67            8 => NavigationError::CanceledBySystem,
68            9 => NavigationError::CanceledByUser,
69            _ => NavigationError::InternalError,
70        }
71    }
72}
73
74#[derive(Debug, thiserror::Error, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
75pub enum GuiServerError {
76    #[error("Unknown internal error")]
77    InternalError,
78
79    #[error("OS error: {:?}", xous::Error::from_usize(*.0))]
80    XousError(usize),
81
82    #[error("navigation error: {0:?}")]
83    Navigation(NavigationError),
84
85    #[error("Cannot close an essential app")]
86    CannotCloseEssentialApp,
87
88    #[error("No app window is registered for that PID")]
89    AppNotFound,
90
91    #[error("The app is already closing")]
92    AppAlreadyClosing,
93}
94
95impl From<xous::Error> for GuiServerError {
96    fn from(e: xous::Error) -> Self { GuiServerError::XousError(e.to_usize()) }
97}
98
99impl AsScalar<3> for GuiServerError {
100    fn as_scalar(&self) -> [u32; 3] {
101        match self {
102            GuiServerError::InternalError => [1, 0, 0],
103            GuiServerError::XousError(e) => [2, *e as u32, 0],
104            GuiServerError::Navigation(e) => {
105                let [kind, arg0, _] = e.as_scalar();
106                [3, kind, arg0]
107            }
108            GuiServerError::CannotCloseEssentialApp => [4, 0, 0],
109            GuiServerError::AppNotFound => [5, 0, 0],
110            GuiServerError::AppAlreadyClosing => [6, 0, 0],
111        }
112    }
113}
114
115impl FromScalar<3> for GuiServerError {
116    fn from_scalar([kind, arg0, arg1]: [u32; 3]) -> Self {
117        match kind {
118            1 => GuiServerError::InternalError,
119            2 => GuiServerError::XousError(arg0 as usize),
120            3 => GuiServerError::Navigation(NavigationError::from_scalar([arg0, arg1, 0])),
121            4 => GuiServerError::CannotCloseEssentialApp,
122            5 => GuiServerError::AppNotFound,
123            6 => GuiServerError::AppAlreadyClosing,
124            _ => GuiServerError::InternalError,
125        }
126    }
127}