Skip to main content
KeyOS API Reference

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    #[error("The navigation request is invalid")]
37    InvalidRequest,
38
39    #[error("The navigation request is not permitted")]
40    PermissionDenied,
41}
42
43impl AsScalar<3> for NavigationError {
44    fn as_scalar(&self) -> [u32; 3] {
45        match self {
46            NavigationError::InternalError => [1, 0, 0],
47            NavigationError::RequestBufferTooSmall => [2, 0, 0],
48            NavigationError::ConcurrentNavigationRequest(pid) => [3, pid.get() as u32, 0],
49            NavigationError::AppIdNotFound => [4, 0, 0],
50            NavigationError::NoNavigationRequest => [5, 0, 0],
51            NavigationError::ModalExited => [6, 0, 0],
52            NavigationError::Locked => [7, 0, 0],
53            NavigationError::CanceledBySystem => [8, 0, 0],
54            NavigationError::CanceledByUser => [9, 0, 0],
55            NavigationError::InvalidRequest => [10, 0, 0],
56            NavigationError::PermissionDenied => [11, 0, 0],
57        }
58    }
59}
60
61impl FromScalar<3> for NavigationError {
62    fn from_scalar([kind, arg, _]: [u32; 3]) -> Self {
63        match kind {
64            1 => NavigationError::InternalError,
65            2 => NavigationError::RequestBufferTooSmall,
66            3 => u8::try_from(arg)
67                .ok()
68                .and_then(xous::PID::new)
69                .map(NavigationError::ConcurrentNavigationRequest)
70                .unwrap_or(NavigationError::InternalError),
71            4 => NavigationError::AppIdNotFound,
72            5 => NavigationError::NoNavigationRequest,
73            6 => NavigationError::ModalExited,
74            7 => NavigationError::Locked,
75            8 => NavigationError::CanceledBySystem,
76            9 => NavigationError::CanceledByUser,
77            10 => NavigationError::InvalidRequest,
78            11 => NavigationError::PermissionDenied,
79            _ => NavigationError::InternalError,
80        }
81    }
82}
83
84#[derive(Debug, thiserror::Error, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
85pub enum GuiServerError {
86    #[error("Unknown internal error")]
87    InternalError,
88
89    #[error("OS error: {:?}", xous::Error::from_usize(*.0))]
90    XousError(usize),
91
92    #[error("navigation error: {0:?}")]
93    Navigation(NavigationError),
94
95    #[error("Cannot close an essential app")]
96    CannotCloseEssentialApp,
97
98    #[error("No app window is registered for that PID")]
99    AppNotFound,
100
101    #[error("The app is already closing")]
102    AppAlreadyClosing,
103}
104
105impl From<xous::Error> for GuiServerError {
106    fn from(e: xous::Error) -> Self { GuiServerError::XousError(e.to_usize()) }
107}
108
109impl AsScalar<3> for GuiServerError {
110    fn as_scalar(&self) -> [u32; 3] {
111        match self {
112            GuiServerError::InternalError => [1, 0, 0],
113            GuiServerError::XousError(e) => [2, *e as u32, 0],
114            GuiServerError::Navigation(e) => {
115                let [kind, arg0, _] = e.as_scalar();
116                [3, kind, arg0]
117            }
118            GuiServerError::CannotCloseEssentialApp => [4, 0, 0],
119            GuiServerError::AppNotFound => [5, 0, 0],
120            GuiServerError::AppAlreadyClosing => [6, 0, 0],
121        }
122    }
123}
124
125impl FromScalar<3> for GuiServerError {
126    fn from_scalar([kind, arg0, arg1]: [u32; 3]) -> Self {
127        match kind {
128            1 => GuiServerError::InternalError,
129            2 => GuiServerError::XousError(arg0 as usize),
130            3 => GuiServerError::Navigation(NavigationError::from_scalar([arg0, arg1, 0])),
131            4 => GuiServerError::CannotCloseEssentialApp,
132            5 => GuiServerError::AppNotFound,
133            6 => GuiServerError::AppAlreadyClosing,
134            _ => GuiServerError::InternalError,
135        }
136    }
137}