use malachite_base::gmp_format;
use malachite_base::strings::gmp_format::{GmpFormatArg, gmp_format, parse_gmp_conversion_spec};
#[test]
fn test_parse_gmp_conversion_spec() {
let (spec, rest) = parse_gmp_conversion_spec(b"#-'8.3Zd tail", &mut || None).unwrap();
assert!(spec.alt);
assert!(spec.left);
assert!(spec.group);
assert_eq!(spec.width, 8);
assert_eq!(spec.prec, Some(3));
assert_eq!(spec.type_chr, b'Z');
assert_eq!(spec.conv, b'd');
assert_eq!(rest, b" tail");
let (spec, _) = parse_gmp_conversion_spec(b"+ d", &mut || None).unwrap();
assert_eq!(spec.sign, b' ');
assert!(spec.plus);
assert!(spec.space);
let (spec, _) = parse_gmp_conversion_spec(b".d", &mut || None).unwrap();
assert_eq!(spec.prec, Some(-1));
let (spec, _) = parse_gmp_conversion_spec(b"d", &mut || None).unwrap();
assert_eq!(spec.prec, None);
let (spec, _) = parse_gmp_conversion_spec(b"lld", &mut || None).unwrap();
assert_eq!(spec.type_chr, b'l');
assert!(spec.type_doubled);
let (spec, _) = parse_gmp_conversion_spec(b"hZd", &mut || None).unwrap();
assert_eq!(spec.type_chr, b'Z');
assert!(!spec.type_doubled);
let (spec, _) = parse_gmp_conversion_spec(b"RZf", &mut || None).unwrap();
assert_eq!(spec.type_chr, b'R');
assert_eq!(spec.rnd_chr, b'Z');
assert_eq!(spec.conv, b'f');
let (spec, _) = parse_gmp_conversion_spec(b"RF", &mut || None).unwrap();
assert_eq!(spec.conv, b'F');
let (spec, _) = parse_gmp_conversion_spec(b"Fe", &mut || None).unwrap();
assert_eq!(spec.type_chr, b'F');
assert_eq!(spec.conv, b'e');
let mut it = [-8i64, 3].into_iter();
let (spec, _) = parse_gmp_conversion_spec(b"*.*d", &mut || it.next()).unwrap();
assert!(spec.left);
assert_eq!(spec.width, 8);
assert_eq!(spec.prec, Some(3));
let mut it = [-3i64].into_iter();
let (spec, _) = parse_gmp_conversion_spec(b".*d", &mut || it.next()).unwrap();
assert_eq!(spec.prec, Some(0));
assert!(parse_gmp_conversion_spec(b"*d", &mut || None).is_none());
assert!(parse_gmp_conversion_spec(b"2147483648d", &mut || None).is_none());
assert!(parse_gmp_conversion_spec(b".2147483648d", &mut || None).is_none());
assert!(parse_gmp_conversion_spec(b"R*f", &mut || None).is_none());
assert!(parse_gmp_conversion_spec(b"", &mut || None).is_none());
assert!(parse_gmp_conversion_spec(b"8", &mut || None).is_none());
assert!(parse_gmp_conversion_spec(b"\xff", &mut || None).is_none());
}
#[test]
fn test_gmp_format_primitive_ints() {
fn test(fmt: &str, arg: &dyn GmpFormatArg, out: Option<&str>) {
assert_eq!(gmp_format(fmt, &[arg]).as_deref(), out, "{fmt}");
}
test("%d", &255u32, Some("255"));
test("%i", &255u32, Some("255"));
test("%u", &255u32, Some("255"));
test("%o", &255u32, Some("377"));
test("%x", &255u32, Some("ff"));
test("%X", &255u32, Some("FF"));
test("%d", &-255i32, Some("-255"));
test("%x", &-255i32, Some("-ff"));
test("%d", &0u8, Some("0"));
test(
"%d",
&u128::MAX,
Some("340282366920938463463374607431768211455"),
);
test("%hd", &255u32, Some("255"));
test("%hhd", &255u32, Some("255"));
test("%ld", &255u64, Some("255"));
test("%lld", &255u64, Some("255"));
test("%jd", &255u64, Some("255"));
test("%zd", &255u64, Some("255"));
test("%td", &255u64, Some("255"));
test("%qd", &255u64, Some("255"));
test("%#x", &255u32, Some("0xff"));
test("%#X", &255u32, Some("0XFF"));
test("%#o", &255u32, Some("0377"));
test("%#x", &0u32, Some("0"));
test("%#o", &0u32, Some("0"));
test("%+d", &255u32, Some("+255"));
test("% d", &255u32, Some(" 255"));
test("%+ d", &255u32, Some("+255"));
test("% +d", &255u32, Some("+255"));
test("%+d", &-255i32, Some("-255"));
test("%8d", &255u32, Some(" 255"));
test("%-8d", &255u32, Some("255 "));
test("%08d", &255u32, Some("00000255"));
test("%+08d", &255u32, Some("+0000255"));
test("%#08x", &255u32, Some("0x0000ff"));
test("%08d", &-255i32, Some("-0000255"));
test("%-08d", &255u32, Some("255 "));
test("%08.5d", &255u32, Some(" 00255"));
test("%.5d", &255u32, Some("00255"));
test("%.0d", &0u32, Some(""));
test("%5.0d", &0u32, Some(" "));
test("%.d", &0u32, Some(""));
test("%'d", &1000000u32, Some("1000000"));
test("%c", &65u32, Some("A"));
test("%c", &321u32, Some("A"));
test("%3c", &65u32, Some(" A"));
test("%s", &255u32, None);
test("%Zd", &255u32, None);
test("%Qd", &255u32, None);
test("%Rf", &255u32, None);
test("%e", &255u32, None);
test("%p", &255u32, None);
test("%n", &255u32, None);
}
#[test]
fn test_gmp_format_char_and_str() {
fn test(fmt: &str, arg: &dyn GmpFormatArg, out: Option<&str>) {
assert_eq!(gmp_format(fmt, &[arg]).as_deref(), out, "{fmt}");
}
test("%c", &'A', Some("A"));
test("%c", &'é', Some("é"));
test("%5c", &'A', Some(" A"));
test("%-5c!", &'A', Some("A !"));
test("%d", &'A', None);
test("%s", &"hello", Some("hello"));
test("%8s", &"hello", Some(" hello"));
test("%-8s!", &"hello", Some("hello !"));
test("%.3s", &"hello", Some("hel"));
test("%.8s", &"hello", Some("hello"));
test("%.0s", &"hello", Some(""));
test("%.1s", &"é", None);
test("%s", &"hello".to_string(), Some("hello"));
test("%d", &"hello", None);
test("%ls", &"hello", None);
}
#[test]
fn test_gmp_format_multiple() {
assert_eq!(
gmp_format("%d + %d = %d", &[&2u32, &2u32, &4u32]).as_deref(),
Some("2 + 2 = 4")
);
assert_eq!(
gmp_format("%c%s%c", &[&'(', &"hello", &')']).as_deref(),
Some("(hello)")
);
assert_eq!(
gmp_format("%0*x", &[&8i32, &255u32]).as_deref(),
Some("000000ff")
);
assert_eq!(
gmp_format("%*d|", &[&-8i32, &255u32]).as_deref(),
Some("255 |")
);
assert_eq!(
gmp_format("%.*d", &[&5u32, &255u32]).as_deref(),
Some("00255")
);
assert_eq!(gmp_format("100%%", &[]).as_deref(), Some("100%"));
assert_eq!(gmp_format("", &[]).as_deref(), Some(""));
assert_eq!(gmp_format("%d", &[&1u32, &2u32]).as_deref(), Some("1"));
assert_eq!(gmp_format("%d %d", &[&5u32]), None);
assert_eq!(gmp_format("%*d", &[&"8", &5u32]), None);
assert_eq!(gmp_format("%s %d", &[&5u32, &"s"]), None);
assert_eq!(
gmp_format!("%s is %d", "x", 5u32).as_deref(),
Some("x is 5")
);
assert_eq!(gmp_format!("no args").as_deref(), Some("no args"));
}