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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#![deny(warnings)]
#![doc(test(attr(deny(warnings))))]
#![doc(test(attr(allow(dead_code))))]
#![doc(test(attr(allow(unused_variables))))]
#![cfg_attr(not(feature="std"), no_std)]
#[cfg(feature="std")]
extern crate core;
#[cfg(not(windows))]
mod unix;
#[cfg(not(windows))]
use unix::*;
#[cfg(windows)]
mod windows;
#[cfg(windows)]
use windows::*;
use core::fmt::{self, Formatter};
#[cfg(feature="std")]
use std::error::Error;
#[cfg(feature="std")]
use std::io::{self};
#[derive(Debug, Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Hash)]
#[repr(transparent)]
pub struct Errno(pub i32);
impl fmt::Display for Errno {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
errno_fmt(self.0, f)
}
}
#[cfg(feature="std")]
impl Error for Errno { }
#[cfg(feature="std")]
impl From<Errno> for io::Error {
fn from(e: Errno) -> Self {
io::Error::from_raw_os_error(e.0)
}
}
pub fn errno() -> Errno { Errno(errno_raw()) }
pub fn set_errno(err: Errno) { set_errno_raw(err.0) }
#[cfg(test)]
mod test {
use crate::*;
use copy_from_str::CopyFromStrExt;
use core::fmt::{self, Write};
use core::str::{self};
use quickcheck_macros::quickcheck;
#[cfg(all(not(windows), not(target_os="macos")))]
use libc::{LC_ALL, EACCES, setlocale};
#[cfg(windows)]
use libc::{LC_ALL, setlocale};
struct Buf<'a> {
s: &'a mut str,
len: usize,
}
impl<'a> Write for Buf<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
let advanced_len = self.len.checked_add(s.len()).unwrap();
self.s[self.len .. advanced_len].copy_from_str(s);
self.len = advanced_len;
Ok(())
}
}
#[quickcheck]
fn errno_after_set_errno(e: i32) -> bool {
set_errno(Errno(e));
errno() == Errno(e)
}
#[quickcheck]
fn error_display(e: i32) -> bool {
if e == 0 { return true; }
let mut buf = [0; 1024];
let buf = str::from_utf8_mut(&mut buf[..]).unwrap();
let mut buf = Buf { s: buf, len: 0 };
write!(&mut buf, "{}", Errno(e)).unwrap();
let res = &buf.s[.. buf.len];
assert!(res.len() > 5);
let end = res.chars().last();
end.is_some() && end.unwrap().is_ascii_alphanumeric() && !end.unwrap().is_whitespace()
}
#[cfg(not(target_os="macos"))]
struct DefaultLocale;
#[cfg(not(target_os="macos"))]
impl Drop for DefaultLocale {
fn drop(&mut self) {
unsafe { setlocale(LC_ALL, b"\0".as_ptr() as *const _); }
}
}
#[cfg(all(not(windows), not(target_os="macos")))]
#[test]
fn localized_messages() {
let _default_locale = DefaultLocale;
let locales: &[&'static [u8]] = &[
b"en_US.UTF-8\0",
b"ja_JP.EUC-JP\0",
b"uk_UA.KOI8-U\0",
b"uk_UA.UTF-8\0"
];
for &locale in locales {
unsafe { setlocale(LC_ALL, locale.as_ptr() as *const _) };
let msg = match locale.split(|&b| b == b'.').next().unwrap() {
b"en_US" => "Permission denied",
b"ja_JP" => "許可がありません",
b"uk_UA" => "Відмовлено у доступі",
_ => panic!("message?"),
};
let mut buf = [0; 1024];
let buf = str::from_utf8_mut(&mut buf[..]).unwrap();
let mut buf = Buf { s: buf, len: 0 };
write!(&mut buf, "{}", Errno(EACCES)).unwrap();
let res = &buf.s[.. buf.len];
assert_eq!(res, msg);
}
}
}