1 /*
2  * Copyright (c) 2024 Google Inc. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 use core::{fmt, num::NonZeroI32};
25 use log::error;
26 use num_traits::FromPrimitive;
27 
28 use crate::sys::Error;
29 
30 impl Error {
from_lk(e: i32) -> Result<(), Self>31     pub fn from_lk(e: i32) -> Result<(), Self> {
32         if e == 0 {
33             return Ok(());
34         }
35         match Error::try_from(NonZeroI32::new(e).unwrap()) {
36             Ok(expected_err) => Err(expected_err),
37             Err(_conversion) => {
38                 error!("don't know how to map {e} to Error");
39                 Err(Error::ERR_INVALID_ARGS)
40             }
41         }
42     }
43 }
44 
45 impl TryFrom<NonZeroI32> for Error {
46     type Error = &'static str;
47 
try_from(e: NonZeroI32) -> Result<Self, Self::Error>48     fn try_from(e: NonZeroI32) -> Result<Self, Self::Error> {
49         match e.get() {
50             e if -45 < e && e < 0 => {
51                 let res = <Error as FromPrimitive>::from_i32(e);
52                 // unwrap must succeed as e was in the valid range
53                 Ok(res.unwrap())
54             }
55             _ => Err("don't know how to map integer to Error"),
56         }
57     }
58 }
59 
60 impl From<Error> for i32 {
from(e: Error) -> i3261     fn from(e: Error) -> i32 {
62         e.0
63     }
64 }
65 
66 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result67     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68         let code = self.0;
69         let msg = match *self {
70             Self::NO_ERROR => "no error",
71             Self::ERR_GENERIC => "generic error",
72             Self::ERR_NOT_FOUND => "not ready",
73             Self::ERR_NO_MSG => "no message",
74             Self::ERR_NO_MEMORY => "no memory",
75             Self::ERR_ALREADY_STARTED => "already started",
76             Self::ERR_NOT_VALID => "not valid",
77             Self::ERR_INVALID_ARGS => "invalid arguments",
78             Self::ERR_NOT_ENOUGH_BUFFER => "not enough buffer",
79             Self::ERR_NOT_SUSPENDED => "not suspended",
80             Self::ERR_OBJECT_DESTROYED => "object destroyed",
81             Self::ERR_NOT_BLOCKED => "not blocked",
82             Self::ERR_TIMED_OUT => "timed out",
83             Self::ERR_ALREADY_EXISTS => "already exists",
84             Self::ERR_CHANNEL_CLOSED => "channel closed",
85             Self::ERR_OFFLINE => "offline",
86             Self::ERR_NOT_ALLOWED => "not allowed",
87             Self::ERR_BAD_PATH => "bad path",
88             Self::ERR_ALREADY_MOUNTED => "already mounted",
89             Self::ERR_IO => "input/output error",
90             Self::ERR_NOT_DIR => "not a directory",
91             Self::ERR_NOT_FILE => "not a file",
92             Self::ERR_RECURSE_TOO_DEEP => "recursion too deep",
93             Self::ERR_NOT_SUPPORTED => "not supported",
94             Self::ERR_TOO_BIG => "too big",
95             Self::ERR_CANCELLED => "cancelled",
96             Self::ERR_NOT_IMPLEMENTED => "not implemented",
97             Self::ERR_CHECKSUM_FAIL => "checksum failure",
98             Self::ERR_CRC_FAIL => "CRC failure",
99             Self::ERR_CMD_UNKNOWN => "command unknown",
100             Self::ERR_BAD_STATE => "bad state",
101             Self::ERR_BAD_LEN => "bad length",
102             Self::ERR_BUSY => "busy",
103             Self::ERR_THREAD_DETACHED => "thread detached",
104             Self::ERR_I2C_NACK => "I2C negative acknowledgement",
105             Self::ERR_ALREADY_EXPIRED => "already expired",
106             Self::ERR_OUT_OF_RANGE => "out of range",
107             Self::ERR_NOT_CONFIGURED => "not configured",
108             Self::ERR_NOT_MOUNTED => "not mounted",
109             Self::ERR_FAULT => "fault",
110             Self::ERR_NO_RESOURCES => "no resources",
111             Self::ERR_BAD_HANDLE => "bad handle",
112             Self::ERR_ACCESS_DENIED => "access denied",
113             Self::ERR_PARTIAL_WRITE => "partial write",
114             Self::ERR_USER_BASE => panic!("attempt to display invalid error code"),
115             _ => unimplemented!("don't know how to display {self:?}"),
116         };
117         write!(f, "{msg} ({code})")
118     }
119 }
120