Skip to content

Instantly share code, notes, and snippets.

@wolfspider
Created December 5, 2024 02:18
Show Gist options
  • Save wolfspider/388090434ba967cedf544189d99cbb94 to your computer and use it in GitHub Desktop.
Save wolfspider/388090434ba967cedf544189d99cbb94 to your computer and use it in GitHub Desktop.
Rust Filter Graph
use buffer::Buffer;
use std::fmt::Debug;
use std::io::{self, BufRead, BufReader, Write};
use std::ops::Deref;
trait Process: Debug {
fn process<'a, B>(&mut self, input: B, output: &mut (impl Buffer<'a> + Write + ?Sized))
where
for<'b> B: BufRead;
}
#[derive(Debug, Clone)]
struct OpStruct<T: Process> {
ops: T,
}
impl<T: Process> Process for OpStruct<T> {
fn process<'a, B>(&mut self, input: B, output: &mut (impl Buffer<'a> + Write + ?Sized))
where
for<'b> B: BufRead,
{
<T as Process>::process(&mut self.ops, input, output)
}
}
impl<T: Process> Deref for OpStruct<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.ops
}
}
type Operations<T> = [OpStruct<T>];
#[derive(Clone)]
enum OpGraph<T: Process + Clone> {
Op(Op<T>),
Sequence(Vec<OpGraph<T>>),
Nil,
}
#[derive(Clone)]
struct Op<T: Process + Clone> {
id: u32,
operations: Box<Operations<T>>,
next: Box<OpGraph<T>>,
}
fn graph<T>(process: T) -> OpGraph<T>
where
T: Process + Clone,
{
OpGraph::Op(Op {
id: 0,
operations: Box::new([OpStruct { ops: process }]),
next: Box::new(OpGraph::Nil),
})
}
// Define MyProcess
#[derive(Debug, Clone)]
struct MyProcess;
// Implement Process for MyProcess
impl Process for MyProcess {
fn process<'a, B>(&mut self, input: B, output: &mut (impl Buffer<'a> + Write + ?Sized))
where
for<'b> B: BufRead,
{
for line in input.lines() {
let outdata: Result<String, std::io::Error> = line;
let out = String::from(outdata.unwrap().to_owned());
println!("{}", out);
let _writeok = output.write(out.as_bytes());
}
}
}
// New function to traverse and print graph details
fn traverse_graph<T: Process + Clone + Debug>(graph: &OpGraph<T>, depth: usize) {
match graph {
OpGraph::Op(op) => {
println!("{}Op:", " ".repeat(depth));
println!("{}id: {}", " ".repeat(depth + 1), op.id);
println!("{}operation: {:?}", " ".repeat(depth + 1), op.operations);
op.operations.clone().iter_mut().for_each(|f| {
let mut input_buffer =
BufReader::new(b"Welcome To The Blacked Scorched Earth!".as_slice());
let mut output_buffer = vec![0u8; 1024];
let _pin =
Box::pin(f.process(&mut input_buffer, &mut output_buffer.as_mut_slice()));
println!(
"Output buffer: {:?}",
String::from_utf8_lossy(&output_buffer[..]).trim_matches('\0')
);
});
traverse_graph(&op.next, depth + 1);
}
OpGraph::Sequence(seq) => {
println!("{}Sequence:", " ".repeat(depth));
for (i, sub_graph) in seq.iter().enumerate() {
println!("{}Item {}:", " ".repeat(depth + 1), i);
traverse_graph(sub_graph, depth + 2);
}
}
OpGraph::Nil => {
println!("{}Nil", " ".repeat(depth));
}
}
}
fn main() -> io::Result<()> {
let my_process: MyProcess = MyProcess;
let simple_graph = graph(my_process.clone());
let nested_graph = OpGraph::Sequence(vec![
graph(MyProcess),
OpGraph::Op(Op {
id: 1,
operations: Box::new([OpStruct { ops: MyProcess }, OpStruct { ops: MyProcess }]),
next: Box::new(graph(MyProcess)),
}),
OpGraph::Nil,
]);
println!("Simple Graph:");
traverse_graph(&simple_graph, 0);
println!("\nNested Graph:");
traverse_graph(&nested_graph, 0);
Ok(())
}
@wolfspider
Copy link
Author

A reddit user had been asking about starting to code a filtergraph and this is what I sent them. It uses the buffer crate which is not the easiest crate to utilize in a setting like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment