pub mod stderr;
pub mod stdin;
pub(crate) mod stdio;
pub mod stdout;
#[cfg(unix)]
use crate::os::unix::io::{
NSTDUnixIOError::{
self, NSTD_UNIX_IO_ERROR_BLOCKING, NSTD_UNIX_IO_ERROR_BROKEN_PIPE,
NSTD_UNIX_IO_ERROR_CONNECTION_RESET, NSTD_UNIX_IO_ERROR_INTERRUPTED,
NSTD_UNIX_IO_ERROR_INVALID_DATA, NSTD_UNIX_IO_ERROR_INVALID_INPUT, NSTD_UNIX_IO_ERROR_NONE,
NSTD_UNIX_IO_ERROR_NOT_FOUND, NSTD_UNIX_IO_ERROR_NO_CONNECTION,
NSTD_UNIX_IO_ERROR_OUT_OF_MEMORY, NSTD_UNIX_IO_ERROR_PERMISSION_DENIED,
NSTD_UNIX_IO_ERROR_TIMED_OUT, NSTD_UNIX_IO_ERROR_UNEXPECTED_EOF,
},
NSTDUnixIOResult,
};
use crate::{
core::{result::NSTDResult, str::NSTDStr},
string::{nstd_string_pop, NSTDString},
vec::NSTDVec,
NSTDUInt,
};
use nstdapi::nstdapi;
use std::io::{ErrorKind, Write};
#[nstdapi]
#[derive(Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum NSTDIOError {
NSTD_IO_ERROR_NONE,
NSTD_IO_ERROR_UNKNOWN,
NSTD_IO_ERROR_NOT_FOUND,
NSTD_IO_ERROR_PERMISSION_DENIED,
NSTD_IO_ERROR_CONNECTION_REFUSED,
NSTD_IO_ERROR_CONNECTION_RESET,
NSTD_IO_ERROR_CONNECTION_TERMINATED,
NSTD_IO_ERROR_NO_CONNECTION,
NSTD_IO_ERROR_SOCKET_IN_USE,
NSTD_IO_ERROR_ADDRESS_NOT_FOUND,
NSTD_IO_ERROR_BROKEN_PIPE,
NSTD_IO_ERROR_ALREADY_EXISTS,
NSTD_IO_ERROR_BLOCKING,
NSTD_IO_ERROR_INVALID_INPUT,
NSTD_IO_ERROR_INVALID_DATA,
NSTD_IO_ERROR_TIMED_OUT,
NSTD_IO_ERROR_WRITE_ZERO,
NSTD_IO_ERROR_INTERRUPTED,
NSTD_IO_ERROR_UNSUPPORTED,
NSTD_IO_ERROR_UNEXPECTED_EOF,
NSTD_IO_ERROR_OUT_OF_MEMORY,
}
impl NSTDIOError {
pub(crate) const fn from_err(err: ErrorKind) -> Self {
match err {
ErrorKind::NotFound => Self::NSTD_IO_ERROR_NOT_FOUND,
ErrorKind::PermissionDenied => Self::NSTD_IO_ERROR_PERMISSION_DENIED,
ErrorKind::ConnectionRefused => Self::NSTD_IO_ERROR_CONNECTION_REFUSED,
ErrorKind::ConnectionReset => Self::NSTD_IO_ERROR_CONNECTION_RESET,
ErrorKind::ConnectionAborted => Self::NSTD_IO_ERROR_CONNECTION_TERMINATED,
ErrorKind::NotConnected => Self::NSTD_IO_ERROR_NO_CONNECTION,
ErrorKind::AddrInUse => Self::NSTD_IO_ERROR_SOCKET_IN_USE,
ErrorKind::AddrNotAvailable => Self::NSTD_IO_ERROR_ADDRESS_NOT_FOUND,
ErrorKind::BrokenPipe => Self::NSTD_IO_ERROR_BROKEN_PIPE,
ErrorKind::AlreadyExists => Self::NSTD_IO_ERROR_ALREADY_EXISTS,
ErrorKind::WouldBlock => Self::NSTD_IO_ERROR_BLOCKING,
ErrorKind::InvalidInput => Self::NSTD_IO_ERROR_INVALID_INPUT,
ErrorKind::InvalidData => Self::NSTD_IO_ERROR_INVALID_DATA,
ErrorKind::TimedOut => Self::NSTD_IO_ERROR_TIMED_OUT,
ErrorKind::WriteZero => Self::NSTD_IO_ERROR_WRITE_ZERO,
ErrorKind::Interrupted => Self::NSTD_IO_ERROR_INTERRUPTED,
ErrorKind::Unsupported => Self::NSTD_IO_ERROR_UNSUPPORTED,
ErrorKind::UnexpectedEof => Self::NSTD_IO_ERROR_UNEXPECTED_EOF,
ErrorKind::OutOfMemory => Self::NSTD_IO_ERROR_OUT_OF_MEMORY,
_ => Self::NSTD_IO_ERROR_UNKNOWN,
}
}
}
#[cfg(unix)]
impl From<NSTDUnixIOError> for NSTDIOError {
fn from(err: NSTDUnixIOError) -> Self {
match err {
NSTD_UNIX_IO_ERROR_NONE => Self::NSTD_IO_ERROR_NONE,
NSTD_UNIX_IO_ERROR_NOT_FOUND => Self::NSTD_IO_ERROR_NOT_FOUND,
NSTD_UNIX_IO_ERROR_PERMISSION_DENIED => Self::NSTD_IO_ERROR_PERMISSION_DENIED,
NSTD_UNIX_IO_ERROR_CONNECTION_RESET => Self::NSTD_IO_ERROR_CONNECTION_RESET,
NSTD_UNIX_IO_ERROR_NO_CONNECTION => Self::NSTD_IO_ERROR_NO_CONNECTION,
NSTD_UNIX_IO_ERROR_BROKEN_PIPE => Self::NSTD_IO_ERROR_BROKEN_PIPE,
NSTD_UNIX_IO_ERROR_BLOCKING => Self::NSTD_IO_ERROR_BLOCKING,
NSTD_UNIX_IO_ERROR_INVALID_INPUT => Self::NSTD_IO_ERROR_INVALID_INPUT,
NSTD_UNIX_IO_ERROR_INVALID_DATA => Self::NSTD_IO_ERROR_INVALID_DATA,
NSTD_UNIX_IO_ERROR_TIMED_OUT => Self::NSTD_IO_ERROR_TIMED_OUT,
NSTD_UNIX_IO_ERROR_INTERRUPTED => Self::NSTD_IO_ERROR_INTERRUPTED,
NSTD_UNIX_IO_ERROR_UNEXPECTED_EOF => Self::NSTD_IO_ERROR_UNEXPECTED_EOF,
NSTD_UNIX_IO_ERROR_OUT_OF_MEMORY => Self::NSTD_IO_ERROR_OUT_OF_MEMORY,
_ => Self::NSTD_IO_ERROR_UNKNOWN,
}
}
}
pub type NSTDIOResult = NSTDResult<NSTDUInt, NSTDIOError>;
#[cfg(unix)]
impl From<NSTDUnixIOResult> for NSTDIOResult {
#[inline]
fn from(value: NSTDUnixIOResult) -> Self {
match value {
NSTDResult::Ok(value) => Self::Ok(value),
NSTDResult::Err(err) => Self::Err(err.into()),
}
}
}
pub type NSTDIOBufferResult<'a> = NSTDResult<NSTDVec<'a>, NSTDIOError>;
pub type NSTDIOStringResult<'a> = NSTDResult<NSTDString<'a>, NSTDIOError>;
#[nstdapi]
pub unsafe fn nstd_io_print(output: &NSTDStr) -> NSTDIOError {
let mut stdout = std::io::stdout();
if let Err(err) = stdout.write_all(output.as_str().as_bytes()) {
return NSTDIOError::from_err(err.kind());
} else if let Err(err) = stdout.flush() {
return NSTDIOError::from_err(err.kind());
}
NSTDIOError::NSTD_IO_ERROR_NONE
}
#[nstdapi]
pub unsafe fn nstd_io_print_line(output: &NSTDStr) -> NSTDIOError {
let mut stdout = std::io::stdout();
if let Err(err) = stdout.write_all(output.as_str().as_bytes()) {
return NSTDIOError::from_err(err.kind());
} else if let Err(err) = stdout.write_all(b"\n") {
return NSTDIOError::from_err(err.kind());
} else if let Err(err) = stdout.flush() {
return NSTDIOError::from_err(err.kind());
}
NSTDIOError::NSTD_IO_ERROR_NONE
}
#[nstdapi]
pub fn nstd_io_read() -> NSTDIOStringResult<'static> {
let mut res = nstd_io_read_line();
if let NSTDResult::Ok(input) = &mut res {
nstd_string_pop(input);
}
res
}
#[nstdapi]
pub fn nstd_io_read_line() -> NSTDIOStringResult<'static> {
let mut input = String::new();
match std::io::stdin().read_line(&mut input) {
Ok(_) => NSTDResult::Ok(NSTDString::from_string(input)),
Err(err) => NSTDResult::Err(NSTDIOError::from_err(err.kind())),
}
}