mirror of
https://github.com/Noratrieb/libuwuc.git
synced 2026-01-14 11:45:05 +01:00
printf
This commit is contained in:
parent
08938636d4
commit
bbe7f04877
2 changed files with 75 additions and 4 deletions
|
|
@ -5,16 +5,36 @@ use crate::{io::IoWrite, utils::SharedThinCstr};
|
|||
pub unsafe fn printf_generic(
|
||||
mut sink: impl IoWrite,
|
||||
format: SharedThinCstr<'_>,
|
||||
_args: VaList<'_, '_>,
|
||||
mut args: VaList<'_, '_>,
|
||||
) -> Result<(), i32> {
|
||||
let mut chars = format.into_iter();
|
||||
|
||||
while let Some(c) = chars.next() {
|
||||
if c == b'%' {
|
||||
todo!();
|
||||
let Some(c) = chars.next() else {
|
||||
return Err(-1);
|
||||
};
|
||||
// todo: do this properly
|
||||
match c {
|
||||
b'c' => {
|
||||
let char = args.arg::<u8>();
|
||||
write!(sink, "{}", char as char)?;
|
||||
}
|
||||
b'l' => {
|
||||
let Some(c) = chars.next() else {
|
||||
return Err(-1);
|
||||
};
|
||||
if c != b'd' {
|
||||
todo!();
|
||||
}
|
||||
let long = args.arg::<i64>();
|
||||
write!(sink, "{}", long)?;
|
||||
}
|
||||
_ => todo!(),
|
||||
};
|
||||
} else {
|
||||
sink.write_byte(c)?;
|
||||
}
|
||||
|
||||
sink.write_byte(c)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -51,4 +71,16 @@ mod tests {
|
|||
fn constant_string() {
|
||||
unsafe { test_printf("hello, world", cstr!("hello, world")) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "variadic")]
|
||||
fn char() {
|
||||
unsafe { test_printf("a", cstr!("%c"), b'a' as u64) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "variadic")]
|
||||
fn long() {
|
||||
unsafe { test_printf("234", cstr!("%ld"), 234_u64) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use core::fmt;
|
||||
|
||||
pub trait IoWrite {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, i32>;
|
||||
|
||||
|
|
@ -12,6 +14,43 @@ pub trait IoWrite {
|
|||
fn write_byte(&mut self, byte: u8) -> Result<(), i32> {
|
||||
self.write_all(&[byte])
|
||||
}
|
||||
|
||||
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<(), i32> {
|
||||
// Create a shim which translates a Write to a fmt::Write and saves
|
||||
// off I/O errors. instead of discarding them
|
||||
struct Adapter<'a, T: ?Sized> {
|
||||
inner: &'a mut T,
|
||||
error: Result<(), i32>,
|
||||
}
|
||||
|
||||
impl<T: IoWrite + ?Sized> fmt::Write for Adapter<'_, T> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
match self.inner.write_all(s.as_bytes()) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(e) => {
|
||||
self.error = Err(e);
|
||||
Err(fmt::Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut output = Adapter {
|
||||
inner: self,
|
||||
error: Ok(()),
|
||||
};
|
||||
match fmt::write(&mut output, fmt) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(..) => {
|
||||
// check if the error came from the underlying `Write` or not
|
||||
if output.error.is_err() {
|
||||
output.error
|
||||
} else {
|
||||
Err(-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: IoWrite> IoWrite for &mut W {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue