# Sing **S**td **I**/o **N**egotiator **G**enerator ## What is sing meant to be? This crate is meant to create interfaces between traits in Rust libraries and the command line. It does this by providing two macros: - `sing_add_trait`, which acts as an attribute to a trait implementation and gathers the method signatures that are used by `sing_loop!`. - `sing_loop!`, which takes a trait object and serialization/deserialization functions as well as some optional parameters. It generates a loop parsing function calls coming from STDIN (or any other `BufRead` stream), evaluating them by calling the appropriate method on the object and returning them on STDOUT (or any other `Write` stream). ## Usage example ```rust use serde::{Serialize, Deserialize}; use sing::{sing_add_trait, sing_loop}; trait FruitTree { fn shake(&self, shakes: u32) -> Vec; } #[derive(Debug, Serialize, Deserialize)] struct Fruit { fruit_type: String, } struct BananaTree; #[sing_add_trait()] impl FruitTree for BananaTree { fn shake(&self, shakes: u32) -> Vec{ let mut out = vec!(); for _ in 0..shakes { out.push(Fruit{fruit_type: String::from("Banana")}); } out } } fn main() { let tree = BananaTree {}; sing_loop!(tree, [different, ron::to_string, ron::from_str],); } ``` ## Negotiator? Really? Yes, it's somewhat far-fetched, but I really wanted to be able to sing and [clap](https://github.com/clap-rs/clap/tree/master/src) in my rusty command-line projects. ## Why the name? See above.