From 5b449f4e1e43bc59109da5a37edf5ec911d3df8e Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 02:13:58 +0200 Subject: IO, error handling --- safe_libc/src/stdio.rs | 102 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 19 deletions(-) (limited to 'safe_libc/src/stdio.rs') diff --git a/safe_libc/src/stdio.rs b/safe_libc/src/stdio.rs index 271f023..2d19725 100644 --- a/safe_libc/src/stdio.rs +++ b/safe_libc/src/stdio.rs @@ -1,47 +1,111 @@ -use crate as libc; -use crate::string; +use crate::{self as libc, errno, string}; use core::fmt; +use core::ops::{Deref, DerefMut}; -pub struct OStream { - file: *mut libc::FILE +pub struct Error { + pub errno: errno::Errno, } +pub type Result = core::result::Result; + +#[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 unsafe fn stdout() -> OStream { - OStream { file: libc::stdout } +pub fn stdout() -> Stdout { + BasicOStream(unsafe { libc::stdout }) } #[inline] -pub unsafe fn stderr() -> OStream { - OStream { file: libc::stderr } +pub fn stderr() -> Stderr { + BasicOStream(unsafe { libc::stderr }) } -impl OStream { +impl BasicOStream { #[inline] - pub fn write(&mut self, b: &[u8]) { - unsafe { + 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.file, - ); + 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 { + if self.write(s.as_bytes()).is_err() { + return Err(fmt::Error); } + 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] - pub fn puts(&mut self, s: &string::CStr) { + fn drop(&mut self) { unsafe { - libc::fputs(s.as_ptr(), self.file); + libc::fclose((self.0).0); } } } -impl fmt::Write for OStream { +impl Deref for OStream { + type Target = BasicOStream; + #[inline] - fn write_str(&mut self, s: &str) -> fmt::Result { - self.write(s.as_bytes()); - Ok(()) + fn deref(&self) -> &BasicOStream { + &self.0 + } +} + +impl DerefMut for OStream { + #[inline] + fn deref_mut(&mut self) -> &mut BasicOStream { + &mut self.0 } } -- cgit v1.2.3