Skip to main content

over_there/core/msg/content/reply/io/
mod.rs

1mod fs;
2mod proc;
3
4pub use fs::*;
5pub use proc::*;
6
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9use std::io;
10
11#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
12pub struct IoErrorArgs {
13    pub description: String,
14    pub os_code: Option<i32>,
15    pub error_kind: SerErrorKind,
16}
17
18impl crate::core::SchemaInfo for IoErrorArgs {}
19
20impl ToString for IoErrorArgs {
21    fn to_string(&self) -> String {
22        self.description.clone()
23    }
24}
25
26impl Default for IoErrorArgs {
27    fn default() -> Self {
28        Self {
29            description: Default::default(),
30            os_code: Default::default(),
31            error_kind: io::ErrorKind::Other.into(),
32        }
33    }
34}
35
36impl IoErrorArgs {
37    pub fn invalid_file_id(id: u32) -> Self {
38        Self {
39            description: format!("No file open with id {}", id),
40            error_kind: io::ErrorKind::InvalidInput.into(),
41            os_code: None,
42        }
43    }
44
45    pub fn invalid_proc_id(id: u32) -> Self {
46        Self {
47            description: format!("No process executed with id {}", id),
48            error_kind: io::ErrorKind::InvalidInput.into(),
49            os_code: None,
50        }
51    }
52
53    pub fn pipe_unavailable() -> Self {
54        Self {
55            description: String::from("Resource unavailable"),
56            error_kind: io::ErrorKind::BrokenPipe.into(),
57            os_code: None,
58        }
59    }
60
61    pub fn from_error_with_prefix(error: io::Error, prefix: &str) -> Self {
62        let mut args = Self::from(error);
63
64        args.description = format!("{}{}", prefix, args.description);
65
66        args
67    }
68}
69
70impl From<io::Error> for IoErrorArgs {
71    fn from(error: io::Error) -> Self {
72        let error_kind = error.kind();
73        let os_code = error.raw_os_error();
74        let description = format!("{}", error);
75
76        Self {
77            description,
78            error_kind: error_kind.into(),
79            os_code,
80        }
81    }
82}
83
84impl Into<io::Error> for IoErrorArgs {
85    fn into(self) -> io::Error {
86        if let Some(code) = self.os_code {
87            io::Error::from_raw_os_error(code)
88        } else {
89            io::Error::new(self.error_kind.into(), self.description)
90        }
91    }
92}
93
94/// This is a hack for us to have both serde serialization and JSON schema
95/// implemented for io::ErrorKind; we have custom serializer/deserializer for
96/// serde but no way to provide a custom function for schema
97#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
98pub enum SerErrorKind {
99    NotFound,
100    PermissionDenied,
101    ConnectionRefused,
102    ConnectionReset,
103    ConnectionAborted,
104    NotConnected,
105    AddrInUse,
106    AddrNotAvailable,
107    BrokenPipe,
108    AlreadyExists,
109    WouldBlock,
110    InvalidInput,
111    InvalidData,
112    TimedOut,
113    WriteZero,
114    Interrupted,
115    Other,
116    UnexpectedEof,
117
118    /// For types that are added later that are not covered
119    NonExhaustive,
120}
121
122impl crate::core::SchemaInfo for SerErrorKind {}
123
124impl From<io::ErrorKind> for SerErrorKind {
125    fn from(error_kind: io::ErrorKind) -> Self {
126        match error_kind {
127            io::ErrorKind::NotFound => Self::NotFound,
128            io::ErrorKind::PermissionDenied => Self::PermissionDenied,
129            io::ErrorKind::ConnectionRefused => Self::ConnectionRefused,
130            io::ErrorKind::ConnectionReset => Self::ConnectionReset,
131            io::ErrorKind::ConnectionAborted => Self::ConnectionAborted,
132            io::ErrorKind::NotConnected => Self::NotConnected,
133            io::ErrorKind::AddrInUse => Self::AddrInUse,
134            io::ErrorKind::AddrNotAvailable => Self::AddrNotAvailable,
135            io::ErrorKind::BrokenPipe => Self::BrokenPipe,
136            io::ErrorKind::AlreadyExists => Self::AlreadyExists,
137            io::ErrorKind::WouldBlock => Self::WouldBlock,
138            io::ErrorKind::InvalidInput => Self::InvalidInput,
139            io::ErrorKind::InvalidData => Self::InvalidData,
140            io::ErrorKind::TimedOut => Self::TimedOut,
141            io::ErrorKind::WriteZero => Self::WriteZero,
142            io::ErrorKind::Interrupted => Self::Interrupted,
143            io::ErrorKind::Other => Self::Other,
144            io::ErrorKind::UnexpectedEof => Self::UnexpectedEof,
145            _ => Self::NonExhaustive,
146        }
147    }
148}
149
150impl From<SerErrorKind> for io::ErrorKind {
151    fn from(ser_error_kind: SerErrorKind) -> Self {
152        match ser_error_kind {
153            SerErrorKind::NotFound => Self::NotFound,
154            SerErrorKind::PermissionDenied => Self::PermissionDenied,
155            SerErrorKind::ConnectionRefused => Self::ConnectionRefused,
156            SerErrorKind::ConnectionReset => Self::ConnectionReset,
157            SerErrorKind::ConnectionAborted => Self::ConnectionAborted,
158            SerErrorKind::NotConnected => Self::NotConnected,
159            SerErrorKind::AddrInUse => Self::AddrInUse,
160            SerErrorKind::AddrNotAvailable => Self::AddrNotAvailable,
161            SerErrorKind::BrokenPipe => Self::BrokenPipe,
162            SerErrorKind::AlreadyExists => Self::AlreadyExists,
163            SerErrorKind::WouldBlock => Self::WouldBlock,
164            SerErrorKind::InvalidInput => Self::InvalidInput,
165            SerErrorKind::InvalidData => Self::InvalidData,
166            SerErrorKind::TimedOut => Self::TimedOut,
167            SerErrorKind::WriteZero => Self::WriteZero,
168            SerErrorKind::Interrupted => Self::Interrupted,
169            SerErrorKind::Other => Self::Other,
170            SerErrorKind::UnexpectedEof => Self::UnexpectedEof,
171
172            // Treat other types as other
173            SerErrorKind::NonExhaustive => Self::Other,
174        }
175    }
176}