1use nstd_core::slice::NSTDSlice;
2use std::{
3 ffi::{CStr, CString},
4 io::{self, prelude::*, BufReader, BufWriter},
5 os::raw::{c_char, c_int},
6 ptr,
7};
8#[cfg(feature = "deps")]
9pub mod deps {
10 pub use nstd_core;
11}
12
13#[inline]
16#[cfg_attr(feature = "clib", no_mangle)]
17pub unsafe extern "C" fn nstd_io_flush() -> c_int {
18 match io::stdout().flush() {
19 Ok(_) => 0,
20 _ => 1,
21 }
22}
23
24#[inline]
29#[cfg_attr(feature = "clib", no_mangle)]
30pub unsafe extern "C" fn nstd_io_write_char(ch: c_char) -> c_int {
31 static_nstd_write(&[ch as u8], io::stdout())
32}
33
34#[inline]
39#[cfg_attr(feature = "clib", no_mangle)]
40pub unsafe extern "C" fn nstd_io_write(str: *const c_char) -> c_int {
41 static_nstd_write(CStr::from_ptr(str).to_bytes(), io::stdout())
42}
43
44#[cfg_attr(feature = "clib", no_mangle)]
49pub unsafe extern "C" fn nstd_io_write_line(str: *const c_char) -> c_int {
50 let mut str = CStr::from_ptr(str).to_string_lossy().to_string();
51 str.push('\n');
52 static_nstd_write(str.as_bytes(), io::stdout())
53}
54
55#[inline]
60#[cfg_attr(feature = "clib", no_mangle)]
61pub unsafe extern "C" fn nstd_io_write_raw(bytes: &NSTDSlice) -> c_int {
62 let bytes = std::slice::from_raw_parts(bytes.ptr.raw.cast(), bytes.byte_count());
63 static_nstd_write(bytes, io::stdout())
64}
65
66#[inline]
69#[cfg_attr(feature = "clib", no_mangle)]
70pub unsafe extern "C" fn nstd_io_flush_err() -> c_int {
71 match io::stderr().flush() {
72 Ok(_) => 0,
73 _ => 1,
74 }
75}
76
77#[inline]
82#[cfg_attr(feature = "clib", no_mangle)]
83pub unsafe extern "C" fn nstd_io_write_char_err(ch: c_char) -> c_int {
84 static_nstd_write(&[ch as u8], io::stderr())
85}
86
87#[inline]
92#[cfg_attr(feature = "clib", no_mangle)]
93pub unsafe extern "C" fn nstd_io_write_err(str: *const c_char) -> c_int {
94 static_nstd_write(CStr::from_ptr(str).to_bytes(), io::stderr())
95}
96
97#[cfg_attr(feature = "clib", no_mangle)]
102pub unsafe extern "C" fn nstd_io_write_line_err(str: *const c_char) -> c_int {
103 let mut str = CStr::from_ptr(str).to_string_lossy().to_string();
104 str.push('\n');
105 static_nstd_write(str.as_bytes(), io::stderr())
106}
107
108#[inline]
113#[cfg_attr(feature = "clib", no_mangle)]
114pub unsafe extern "C" fn nstd_io_write_raw_err(bytes: &NSTDSlice) -> c_int {
115 let bytes = std::slice::from_raw_parts(bytes.ptr.raw.cast(), bytes.byte_count());
116 static_nstd_write(bytes, io::stderr())
117}
118
119#[cfg_attr(feature = "clib", no_mangle)]
124pub unsafe extern "C" fn nstd_io_read_char(errc: *mut c_int) -> c_char {
125 let mut byte = [0];
126 match BufReader::new(io::stdin()).read_exact(&mut byte) {
127 Ok(_) => {
128 *errc = 0;
129 byte[0] as c_char
130 }
131 _ => {
132 *errc = 1;
133 0
134 }
135 }
136}
137
138#[cfg_attr(feature = "clib", no_mangle)]
143pub unsafe extern "C" fn nstd_io_read(errc: *mut c_int) -> *mut c_char {
144 let mut bytes = static_nstd_read(errc);
145 match *errc {
146 0 => {
147 let mut len = bytes.len();
148 while len > 0 && bytes[len - 1].is_ascii_whitespace() {
149 bytes.pop();
150 len -= 1;
151 }
152 bytes.push(0);
153 CString::from_vec_unchecked(bytes).into_raw()
154 }
155 _ => ptr::null_mut(),
156 }
157}
158
159#[cfg_attr(feature = "clib", no_mangle)]
164pub unsafe extern "C" fn nstd_io_read_line(errc: *mut c_int) -> *mut c_char {
165 let mut bytes = static_nstd_read(errc);
166 bytes.push(b'\0');
167 CString::from_vec_unchecked(bytes).into_raw()
168}
169
170#[inline]
174#[cfg_attr(feature = "clib", no_mangle)]
175pub unsafe extern "C" fn nstd_io_free_read(str: *mut *mut c_char) {
176 drop(CString::from_raw(*str));
177 *str = ptr::null_mut();
178}
179
180fn static_nstd_write<Stream: Write>(bytes: &[u8], stream: Stream) -> c_int {
182 let mut buf = BufWriter::new(stream);
183 match buf.write_all(bytes) {
184 Ok(_) => match buf.flush() {
185 Ok(_) => 0,
186 _ => 1,
187 },
188 _ => 1,
189 }
190}
191
192unsafe fn static_nstd_read(errc: *mut c_int) -> Vec<u8> {
194 let mut string = String::new();
195 *errc = match BufReader::new(io::stdin()).read_line(&mut string) {
196 Ok(_) => 0,
197 _ => 1,
198 };
199 string.into_bytes()
200}