use std::fmt::{Debug, Display};
use std::io::Write;
use crate::node::Node;
pub struct WriterNode<W> {
writer: W,
}
impl<W> WriterNode<W> {
pub fn new(writer: W) -> Self {
Self { writer }
}
pub fn writer_mut(&mut self) -> &mut W {
&mut self.writer
}
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W> Node for WriterNode<W>
where
W: Write + Send + Sync,
{
type Input = Vec<u8>;
type Output = Result<(), std::io::Error>;
type Error = std::io::Error;
async fn process(&mut self, input: Vec<u8>) -> Result<(), std::io::Error> {
self.writer.write_all(&input)?;
self.writer.flush()?;
Ok(())
}
}
pub struct StringWriterNode<W> {
writer: W,
add_newline: bool,
}
impl<W> StringWriterNode<W> {
pub fn new(writer: W) -> Self {
Self { writer, add_newline: false }
}
pub fn with_newline(mut self, add_newline: bool) -> Self {
self.add_newline = add_newline;
self
}
pub fn writer_mut(&mut self) -> &mut W {
&mut self.writer
}
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W> Node for StringWriterNode<W>
where
W: Write + Send + Sync,
{
type Input = String;
type Output = Result<(), std::io::Error>;
type Error = std::io::Error;
async fn process(&mut self, input: String) -> Result<(), std::io::Error> {
self.writer.write_all(input.as_bytes())?;
if self.add_newline {
self.writer.write_all(b"\n")?;
}
self.writer.flush()?;
Ok(())
}
}
pub struct DisplayWriterNode<W, T> {
writer: W,
_marker: std::marker::PhantomData<T>,
}
impl<W, T> DisplayWriterNode<W, T> {
pub fn new(writer: W) -> Self {
Self { writer, _marker: std::marker::PhantomData }
}
pub fn writer_mut(&mut self) -> &mut W {
&mut self.writer
}
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W, T> Node for DisplayWriterNode<W, T>
where
W: Write + Send + Sync,
T: Display + Send + Sync,
{
type Input = T;
type Output = Result<(), std::io::Error>;
type Error = std::io::Error;
async fn process(&mut self, input: T) -> Result<(), std::io::Error> {
writeln!(self.writer, "{}", input)?;
Ok(())
}
}
pub struct DebugWriterNode<W, T> {
writer: W,
_marker: std::marker::PhantomData<T>,
}
impl<W, T> DebugWriterNode<W, T> {
pub fn new(writer: W) -> Self {
Self { writer, _marker: std::marker::PhantomData }
}
pub fn writer_mut(&mut self) -> &mut W {
&mut self.writer
}
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W, T> Node for DebugWriterNode<W, T>
where
W: Write + Send + Sync,
T: Debug + Send + Sync,
{
type Input = T;
type Output = Result<(), std::io::Error>;
type Error = std::io::Error;
async fn process(&mut self, input: T) -> Result<(), std::io::Error> {
writeln!(self.writer, "{:?}", input)?;
Ok(())
}
}
pub fn stdout_writer() -> WriterNode<std::io::Stdout> {
WriterNode::new(std::io::stdout())
}
pub fn stderr_writer() -> WriterNode<std::io::Stderr> {
WriterNode::new(std::io::stderr())
}
pub fn stdout_display_writer<T>() -> DisplayWriterNode<std::io::Stdout, T>
where
T: Display + Send + Sync,
{
DisplayWriterNode::new(std::io::stdout())
}
pub fn stderr_display_writer<T>() -> DisplayWriterNode<std::io::Stderr, T>
where
T: Display + Send + Sync,
{
DisplayWriterNode::new(std::io::stderr())
}
pub fn stdout_debug_writer<T>() -> DebugWriterNode<std::io::Stdout, T>
where
T: Debug + Send + Sync,
{
DebugWriterNode::new(std::io::stdout())
}
pub fn stderr_debug_writer<T>() -> DebugWriterNode<std::io::Stderr, T>
where
T: Debug + Send + Sync,
{
DebugWriterNode::new(std::io::stderr())
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_writer_node_with_vec() {
let mut buffer = Vec::new();
let mut writer = WriterNode::new(&mut buffer);
writer.process(b"Hello, World!".to_vec()).await.unwrap();
assert_eq!(buffer, b"Hello, World!");
}
#[tokio::test]
async fn test_writer_node_multiple_writes() {
let mut buffer = Vec::new();
let mut writer = WriterNode::new(&mut buffer);
writer.process(b"First".to_vec()).await.unwrap();
writer.process(b" Second".to_vec()).await.unwrap();
assert_eq!(buffer, b"First Second");
}
#[tokio::test]
async fn test_writer_node_empty_input() {
let mut buffer = Vec::new();
let mut writer = WriterNode::new(&mut buffer);
writer.process(b"".to_vec()).await.unwrap();
assert_eq!(buffer, b"");
}
#[tokio::test]
async fn test_writer_node_binary_data() {
let mut buffer = Vec::new();
let mut writer = WriterNode::new(&mut buffer);
let binary_data: Vec<u8> = vec![0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD];
writer.process(binary_data.clone()).await.unwrap();
assert_eq!(buffer, binary_data);
}
#[tokio::test]
async fn test_writer_node_writer_mut() {
let mut buffer = Vec::new();
let mut writer = WriterNode::new(&mut buffer);
writer.writer_mut().write_all(b"Direct").unwrap();
writer.writer_mut().flush().unwrap();
assert_eq!(buffer, b"Direct");
}
#[tokio::test]
async fn test_writer_node_into_inner() {
let buffer: Vec<u8> = Vec::new();
let writer = WriterNode::new(buffer);
let inner_buffer = writer.into_inner();
assert!(inner_buffer.is_empty());
}
#[tokio::test]
async fn test_string_writer_node_without_newline() {
let mut buffer = Vec::new();
let mut writer = StringWriterNode::new(&mut buffer);
writer.process("Hello".to_string()).await.unwrap();
assert_eq!(buffer, b"Hello");
}
#[tokio::test]
async fn test_string_writer_node_with_newline() {
let mut buffer = Vec::new();
let mut writer = StringWriterNode::new(&mut buffer).with_newline(true);
writer.process("Hello".to_string()).await.unwrap();
assert_eq!(buffer, b"Hello\n");
}
#[tokio::test]
async fn test_string_writer_node_multiple_lines() {
let mut buffer = Vec::new();
let mut writer = StringWriterNode::new(&mut buffer).with_newline(true);
writer.process("Line 1".to_string()).await.unwrap();
writer.process("Line 2".to_string()).await.unwrap();
writer.process("Line 3".to_string()).await.unwrap();
assert_eq!(buffer, b"Line 1\nLine 2\nLine 3\n");
}
#[tokio::test]
async fn test_string_writer_node_empty_string() {
let mut buffer = Vec::new();
let mut writer = StringWriterNode::new(&mut buffer);
writer.process("".to_string()).await.unwrap();
assert_eq!(buffer, b"");
}
#[tokio::test]
async fn test_string_writer_node_unicode() {
let mut buffer = Vec::new();
let mut writer = StringWriterNode::new(&mut buffer);
writer.process("你好,世界!".to_string()).await.unwrap();
assert_eq!(buffer, "你好,世界!".as_bytes());
}
#[tokio::test]
async fn test_string_writer_node_writer_mut() {
let mut buffer = Vec::new();
let mut writer = StringWriterNode::new(&mut buffer);
writer.writer_mut().write_all(b"Direct").unwrap();
writer.writer_mut().flush().unwrap();
assert_eq!(buffer, b"Direct");
}
#[tokio::test]
async fn test_string_writer_node_into_inner() {
let buffer: Vec<u8> = Vec::new();
let writer = StringWriterNode::new(buffer);
let inner_buffer = writer.into_inner();
assert!(inner_buffer.is_empty());
}
#[tokio::test]
async fn test_display_writer_node_string() {
let mut buffer = Vec::new();
let mut writer = DisplayWriterNode::<_, String>::new(&mut buffer);
writer.process("Test".to_string()).await.unwrap();
assert_eq!(buffer, b"Test\n");
}
#[tokio::test]
async fn test_display_writer_node_integer() {
let mut buffer = Vec::new();
let mut writer = DisplayWriterNode::<_, i32>::new(&mut buffer);
writer.process(42).await.unwrap();
assert_eq!(buffer, b"42\n");
}
#[tokio::test]
async fn test_display_writer_node_float() {
let mut buffer = Vec::new();
let mut writer = DisplayWriterNode::<_, f64>::new(&mut buffer);
writer.process(std::f64::consts::PI).await.unwrap();
assert_eq!(buffer, b"3.141592653589793\n");
}
#[tokio::test]
async fn test_display_writer_node_multiple_values() {
let mut buffer = Vec::new();
let mut writer = DisplayWriterNode::<_, String>::new(&mut buffer);
writer.process("10".to_string()).await.unwrap();
writer.process("20.5".to_string()).await.unwrap();
writer.process("Hello".to_string()).await.unwrap();
assert_eq!(buffer, b"10\n20.5\nHello\n");
}
#[tokio::test]
async fn test_display_writer_node_unicode() {
let mut buffer = Vec::new();
let mut writer = DisplayWriterNode::<_, String>::new(&mut buffer);
writer.process("你好".to_string()).await.unwrap();
assert_eq!(buffer, b"\xe4\xbd\xa0\xe5\xa5\xbd\n");
}
#[tokio::test]
async fn test_display_writer_node_writer_mut() {
let mut buffer = Vec::new();
let mut writer = DisplayWriterNode::<_, String>::new(&mut buffer);
writer.writer_mut().write_all(b"Direct\n").unwrap();
assert_eq!(buffer, b"Direct\n");
}
#[tokio::test]
async fn test_display_writer_node_into_inner() {
let buffer: Vec<u8> = Vec::new();
let writer = DisplayWriterNode::<_, String>::new(buffer);
let inner_buffer = writer.into_inner();
assert!(inner_buffer.is_empty());
}
#[tokio::test]
async fn test_debug_writer_node_string() {
let mut buffer = Vec::new();
let mut writer = DebugWriterNode::<_, String>::new(&mut buffer);
writer.process("Test".to_string()).await.unwrap();
assert_eq!(buffer, b"\"Test\"\n");
}
#[tokio::test]
async fn test_debug_writer_node_vector() {
let mut buffer = Vec::new();
let mut writer = DebugWriterNode::<_, Vec<i32>>::new(&mut buffer);
writer.process(vec![1, 2, 3]).await.unwrap();
assert_eq!(buffer, b"[1, 2, 3]\n");
}
#[tokio::test]
async fn test_debug_writer_node_tuple() {
let mut buffer = Vec::new();
let mut writer = DebugWriterNode::<_, (i32, String)>::new(&mut buffer);
writer.process((42, "hello".to_string())).await.unwrap();
assert_eq!(buffer, b"(42, \"hello\")\n");
}
#[tokio::test]
async fn test_debug_writer_node_struct() {
#[derive(Debug)]
#[allow(dead_code)]
struct Point {
x: i32,
y: i32,
}
let mut buffer = Vec::new();
let mut writer = DebugWriterNode::<_, Point>::new(&mut buffer);
let p = Point { x: 10, y: 20 };
writer.process(p).await.unwrap();
assert_eq!(buffer, b"Point { x: 10, y: 20 }\n");
}
#[tokio::test]
async fn test_debug_writer_node_option() {
let mut buffer = Vec::new();
let mut writer = DebugWriterNode::<_, Option<i32>>::new(&mut buffer);
writer.process(Some(42)).await.unwrap();
writer.process(None).await.unwrap();
assert_eq!(buffer, b"Some(42)\nNone\n");
}
#[tokio::test]
async fn test_debug_writer_node_writer_mut() {
let mut buffer = Vec::new();
let mut writer = DebugWriterNode::<_, String>::new(&mut buffer);
writer.writer_mut().write_all(b"Direct\n").unwrap();
assert_eq!(buffer, b"Direct\n");
}
#[tokio::test]
async fn test_debug_writer_node_into_inner() {
let buffer: Vec<u8> = Vec::new();
let writer = DebugWriterNode::<_, String>::new(buffer);
let inner_buffer = writer.into_inner();
assert!(inner_buffer.is_empty());
}
#[tokio::test]
async fn test_stdout_writer() {
let mut writer = stdout_writer();
writer.process(b"Test output".to_vec()).await.unwrap();
}
#[tokio::test]
async fn test_stderr_writer() {
let mut writer = stderr_writer();
writer.process(b"Test error".to_vec()).await.unwrap();
}
#[tokio::test]
async fn test_stdout_display_writer() {
let mut writer = stdout_display_writer::<i32>();
writer.process(42).await.unwrap();
}
#[tokio::test]
async fn test_stderr_display_writer() {
let mut writer = stderr_display_writer::<String>();
writer
.process("Test error display".to_string())
.await
.unwrap();
}
#[tokio::test]
async fn test_stdout_debug_writer() {
let mut writer = stdout_debug_writer::<Vec<i32>>();
writer.process(vec![1, 2, 3]).await.unwrap();
}
#[tokio::test]
async fn test_stderr_debug_writer() {
let mut writer = stderr_debug_writer::<Option<i32>>();
writer.process(Some(42)).await.unwrap();
}
#[tokio::test]
async fn test_writer_node_large_data() {
let mut buffer = Vec::new();
let mut writer = WriterNode::new(&mut buffer);
let large_data = vec![b'X'; 10_000];
writer.process(large_data.clone()).await.unwrap();
assert_eq!(buffer, large_data);
}
#[tokio::test]
async fn test_string_writer_node_special_chars() {
let mut buffer = Vec::new();
let mut writer = StringWriterNode::new(&mut buffer);
let special = "Tab:\t, Newline:\n, Quote: \"".to_string();
writer.process(special.clone()).await.unwrap();
assert_eq!(buffer, special.as_bytes());
}
#[tokio::test]
async fn test_string_writer_node_multiline_content() {
let mut buffer = Vec::new();
let mut writer = StringWriterNode::new(&mut buffer);
writer.process("Line 1\nLine 2".to_string()).await.unwrap();
assert_eq!(buffer, b"Line 1\nLine 2");
}
}