-
Notifications
You must be signed in to change notification settings - Fork 467
/
Copy pathcommon.rs
102 lines (88 loc) · 2.79 KB
/
common.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use std::ffi::{CString, NulError};
use std::{error, fmt, io};
#[derive(Debug)]
pub struct SdlError {
msg: String,
}
impl SdlError {
pub fn from_last_error() -> Self {
let msg = crate::get_error();
Self { msg }
}
pub(crate) fn from_string(msg: String) -> Self {
Self { msg }
}
pub fn message(&self) -> &str {
&self.msg
}
}
impl fmt::Display for SdlError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl error::Error for SdlError {}
#[derive(Debug)]
pub enum Error {
Sdl(SdlError),
Io(io::Error),
/// An integer was larger than [`i32::MAX`] in a parameter, and it can't be converted to a C int
IntOverflow(&'static str, u32),
/// A null byte was found within a parameter, and it can't be sent to SDL
InvalidString(NulError, &'static str),
}
impl Error {
pub fn from_sdl_error() -> Self {
Self::Sdl(SdlError::from_last_error())
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Sdl(msg) => write!(f, "SDL error: {msg}"),
Self::Io(err) => write!(f, "IO error: {err}"),
Self::IntOverflow(name, value) => write!(f, "Integer '{name}' overflows: {value}"),
Self::InvalidString(name, nul) => write!(f, "Invalid string '{name}': {nul}"),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Self::Sdl(..) | Self::IntOverflow(..) => None,
Self::Io(err) => Some(err),
Self::InvalidString(nul, _) => Some(nul),
}
}
}
impl From<SdlError> for Error {
fn from(value: SdlError) -> Self {
Self::Sdl(value)
}
}
impl From<io::Error> for Error {
fn from(value: io::Error) -> Self {
Self::Io(value)
}
}
pub fn validate_string(str: impl Into<Vec<u8>>, name: &'static str) -> Result<CString, Error> {
match CString::new(str) {
Ok(c) => Ok(c),
Err(nul) => Err(Error::InvalidString(nul, name)),
}
}
/// Validates and converts the given u32 to a positive C integer.
pub fn validate_int(value: u32, name: &'static str) -> Result<libc::c_int, Error> {
// Many SDL functions will accept `int` values, even if it doesn't make sense
// for the values to be negative.
// In the cases that SDL doesn't check negativity, passing negative values
// could be unsafe.
// For example, `SDL_JoystickGetButton` uses the index argument to access an
// array without checking if it's negative, which could potentially lead to
// segmentation faults.
if value > libc::c_int::MAX as u32 {
Err(Error::IntOverflow(name, value))
} else {
Ok(value as libc::c_int)
}
}