use std::fmt::{self, Write}; use indent_write::fmt::IndentWriter; // This is a wrapper for fmt::Write that only writes one char at a time, to test // the invariants of IndentableWrite #[derive(Debug, Clone)] struct OneByteAtATime(W); impl Write for OneByteAtATime { fn write_str(&mut self, s: &str) -> fmt::Result { s.chars().try_for_each(|c| self.0.write_char(c)) } fn write_char(&mut self, c: char) -> fmt::Result { self.0.write_char(c) } } const CONTENT: &'static [&'static str] = &["\tšŸ˜€ šŸ˜€ šŸ˜€", "\t\tšŸ˜€ šŸ˜€ šŸ˜€", "\tšŸ˜€ šŸ˜€ šŸ˜€"]; // Using a function to wrap a writer, run a standard test and check against expected macro_rules! test_harness { ($target:ident => $transform:expr, expect: $result:expr) => {{ let mut dest = String::new(); { let $target = &mut dest; let mut indented_dest = $transform; for line in CONTENT { write!(&mut indented_dest, "{}\n", line).unwrap(); } } assert_eq!(dest, $result); }}; } #[test] fn basic_test() { let mut dest = String::new(); { let mut writer = IndentWriter::new("\t", &mut dest); for line in CONTENT { writeln!(writer, "{}", line).unwrap(); } } assert_eq!(dest, "\t\tšŸ˜€ šŸ˜€ šŸ˜€\n\t\t\tšŸ˜€ šŸ˜€ šŸ˜€\n\t\tšŸ˜€ šŸ˜€ šŸ˜€\n"); } #[test] fn test_prefix() { test_harness!(w => IndentWriter::new(" ", w), expect: " \tšŸ˜€ šŸ˜€ šŸ˜€\n \t\tšŸ˜€ šŸ˜€ šŸ˜€\n \tšŸ˜€ šŸ˜€ šŸ˜€\n") } #[test] fn test_multi_indent() { let mut dest = String::new(); writeln!(dest, "{}", "šŸ˜€ šŸ˜€ šŸ˜€").unwrap(); { let mut indent1 = IndentWriter::new("\t", &mut dest); writeln!(indent1, "{}", "šŸ˜€ šŸ˜€ šŸ˜€").unwrap(); { let mut indent2 = IndentWriter::new("\t", &mut indent1); writeln!(indent2, "{}", "šŸ˜€ šŸ˜€ šŸ˜€").unwrap(); { let mut indent3 = IndentWriter::new("\t", &mut indent2); writeln!(indent3, "{}", "šŸ˜€ šŸ˜€ šŸ˜€").unwrap(); writeln!(indent3, "").unwrap(); } writeln!(indent2, "{}", "šŸ˜€ šŸ˜€ šŸ˜€").unwrap(); } writeln!(indent1, "{}", "šŸ˜€ šŸ˜€ šŸ˜€").unwrap(); } assert_eq!( dest, "šŸ˜€ šŸ˜€ šŸ˜€ \tšŸ˜€ šŸ˜€ šŸ˜€ \t\tšŸ˜€ šŸ˜€ šŸ˜€ \t\t\tšŸ˜€ šŸ˜€ šŸ˜€ \t\tšŸ˜€ šŸ˜€ šŸ˜€ \tšŸ˜€ šŸ˜€ šŸ˜€\n" ) } // Technically this doesn't test anything in the crate, it just ensures that OneByteAtATime works #[test] fn test_partial_writes() { let mut dest = String::new(); { let mut partial_writer = OneByteAtATime(&mut dest); write!(partial_writer, "Hello, {}!", "World").unwrap(); } assert_eq!(dest, "Hello, World!"); } #[test] fn test_partial_simple_indent_writes() { let mut dest = String::new(); { let writer = OneByteAtATime(&mut dest); let mut writer = IndentWriter::new("\t", writer); writeln!(writer, "{}", "Hello, World").unwrap(); writeln!(writer, "{}", "šŸ˜€ šŸ˜€ šŸ˜€\nšŸ˜€ šŸ˜€ šŸ˜€").unwrap(); } assert_eq!(dest, "\tHello, World\n\tšŸ˜€ šŸ˜€ šŸ˜€\n\tšŸ˜€ šŸ˜€ šŸ˜€\n"); } #[test] fn test_partial_simple_indent_writes_inverted() { let mut dest = String::new(); { let writer = IndentWriter::new("\t", &mut dest); let mut writer = OneByteAtATime(writer); writeln!(writer, "{}", "Hello, World").unwrap(); writeln!(writer, "{}", "šŸ˜€ šŸ˜€ šŸ˜€\nšŸ˜€ šŸ˜€ šŸ˜€").unwrap(); } assert_eq!(dest, "\tHello, World\n\tšŸ˜€ šŸ˜€ šŸ˜€\n\tšŸ˜€ šŸ˜€ šŸ˜€\n"); } #[test] fn test_partial_writes_combined() { let mut dest = String::new(); { let writer = OneByteAtATime(&mut dest); let writer = IndentWriter::new(" ", writer); let mut writer = OneByteAtATime(writer); writeln!(writer, "{}", "Hello, World").unwrap(); writeln!(writer, "{}", "šŸ˜€ šŸ˜€ šŸ˜€\nšŸ˜€ šŸ˜€ šŸ˜€").unwrap(); } assert_eq!(dest, " Hello, World\n šŸ˜€ šŸ˜€ šŸ˜€\n šŸ˜€ šŸ˜€ šŸ˜€\n"); }