summaryrefslogtreecommitdiffstats
path: root/safe_libc/src/stdio.rs
blob: 294240562f8cc8f2387128efd5696432194ad9d5 (plain)
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
use crate::{self as libc, errno, string};

use core::fmt;
use core::ops::{Deref, DerefMut};

pub struct Error {
	pub errno: errno::Errno,
}

impl From<Error> for fmt::Error {
	fn from(_err: Error) -> fmt::Error {
		fmt::Error
	}
}

pub type Result<T> = core::result::Result<T, Error>;

#[inline]
fn check_io(ok: bool) -> Result<()> {
	if ok {
		Ok(())
	} else {
		Err(Error {
			errno: errno::errno(),
		})
	}
}

pub struct BasicOStream(*mut libc::FILE);

unsafe impl Sync for BasicOStream {}
unsafe impl Send for BasicOStream {}

pub type Stdout = BasicOStream;
pub type Stderr = BasicOStream;

#[inline]
pub fn stdout() -> Stdout {
	BasicOStream(unsafe { libc::stdout })
}

#[inline]
pub fn stderr() -> Stderr {
	BasicOStream(unsafe { libc::stderr })
}

impl BasicOStream {
	#[inline]
	pub fn flush(&mut self) -> Result<()> {
		check_io(unsafe { libc::fflush(self.0) } == 0)
	}

	#[inline]
	pub fn write(&mut self, b: &[u8]) -> Result<()> {
		check_io(unsafe { libc::fwrite(b.as_ptr().cast(), 1, b.len(), self.0) } == b.len())
	}

	#[inline]
	pub fn puts(&mut self, s: &string::CStr) -> Result<()> {
		check_io(unsafe { libc::fputs(s.as_ptr(), self.0) } != libc::EOF)
	}
}

impl fmt::Write for BasicOStream {
	#[inline]
	fn write_str(&mut self, s: &str) -> fmt::Result {
		self.write(s.as_bytes())?;
		Ok(())
	}
}

pub struct OStream(BasicOStream);

impl OStream {
	#[inline]
	pub unsafe fn from_raw(file: *mut libc::FILE) -> OStream {
		OStream(BasicOStream(file))
	}
}

impl Drop for OStream {
	#[inline]
	fn drop(&mut self) {
		unsafe {
			libc::fclose((self.0).0);
		}
	}
}

impl Deref for OStream {
	type Target = BasicOStream;

	#[inline]
	fn deref(&self) -> &BasicOStream {
		&self.0
	}
}

impl DerefMut for OStream {
	#[inline]
	fn deref_mut(&mut self) -> &mut BasicOStream {
		&mut self.0
	}
}