use std::convert::TryInto;
use std::ffi::CString;
use std::os::raw::c_char;
use libc::snprintf;
use sprintf::*;
fn check_fmt<T: Printf>(fmt: &str, arg: T) {
let our_result = sprintf!(fmt, arg).unwrap();
let mut buf = vec![0_u8; our_result.len() + 1];
let cfmt = CString::new(fmt).unwrap();
let clen: usize = unsafe {
snprintf(
buf.as_mut_ptr() as *mut c_char,
buf.len(),
cfmt.as_ptr(),
arg,
)
}
.try_into()
.unwrap();
buf.truncate(clen); let c_result = String::from_utf8(buf).unwrap();
assert_eq!(our_result, c_result);
}
fn check_fmt_s(fmt: &str, arg: &str) {
let our_result = sprintf!(fmt, arg).unwrap();
let mut buf = vec![0_u8; our_result.len() + 1];
let cfmt = CString::new(fmt).unwrap();
let carg = CString::new(arg).unwrap();
let clen: usize = unsafe {
snprintf(
buf.as_mut_ptr() as *mut c_char,
buf.len(),
cfmt.as_ptr(),
carg.as_ptr(),
)
}
.try_into()
.unwrap();
buf.truncate(clen); let c_result = String::from_utf8(buf).unwrap();
assert_eq!(our_result, c_result);
}
#[test]
fn test_int() {
check_fmt("%d", 12);
check_fmt("~%d~", 148);
check_fmt("00%dxx", -91232);
check_fmt("%x", -9232);
check_fmt("%X", 432);
check_fmt("%09X", 432);
check_fmt("%9X", 432);
check_fmt("%+9X", 492);
check_fmt("% #9x", 4589);
check_fmt("%2o", 4);
check_fmt("% 12d", -4);
check_fmt("% 12d", 48);
check_fmt("%ld", -4_i64);
check_fmt("%lX", -4_i64);
check_fmt("%ld", 48_i64);
check_fmt("%-8hd", -12_i16);
check_fmt("%llx", 0x0123456789abcdef_u64);
}
#[test]
fn test_float() {
check_fmt("%f", -46.38);
check_fmt("%012.3f", 1.2);
check_fmt("%012.3e", 1.7);
check_fmt("%e", 1e300);
check_fmt("%012.3g%%!", 2.6);
check_fmt("%012.5G", -2.69);
check_fmt("%+7.4f", 42.785);
check_fmt("{}% 7.4E", 493.12);
check_fmt("% 7.4E", -120.3);
check_fmt("%-10F", f64::INFINITY);
check_fmt("%+010F", f64::INFINITY);
check_fmt("% f", f64::NAN);
check_fmt("%+f", f64::NAN);
check_fmt("%.1f", 999.99);
check_fmt("%.1f", 9.99);
check_fmt("%.1e", 9.99);
check_fmt("%.2f", 9.99);
check_fmt("%.2e", 9.99);
check_fmt("%.3f", 9.99);
check_fmt("%.3e", 9.99);
check_fmt("%.1g", 9.99);
check_fmt("%.1G", 9.99);
check_fmt("%.1f", 2.99);
check_fmt("%.1e", 2.99);
check_fmt("%.1g", 2.99);
check_fmt("%.1f", 2.599);
check_fmt("%.1e", 2.599);
check_fmt("%.1g", 2.599);
}
#[test]
fn test_str() {
check_fmt_s("test %% with string: %s yay\n", "FOO");
check_fmt("test char %c", '~');
}