65 lines
1.8 KiB
Markdown
65 lines
1.8 KiB
Markdown
# Sing
|
|
|
|
**S**td
|
|
|
|
**I**/o
|
|
|
|
**N**egotiator
|
|
|
|
**G**enerator
|
|
|
|
[![Crates.io](https://img.shields.io/crates/v/sing_rs)](https://crates.io/crates/sing_rs)
|
|
[![License](https://img.shields.io/crates/l/sing_rs)](https://www.gnu.org/licenses/agpl-3.0.html)
|
|
|
|
## What is sing?
|
|
|
|
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_rs::{sing_add_trait, sing_loop};
|
|
|
|
trait FruitTree {
|
|
fn shake(&self, shakes: u32) -> Vec<Fruit>;
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
struct Fruit {
|
|
fruit_type: String,
|
|
}
|
|
|
|
struct BananaTree;
|
|
|
|
#[sing_add_trait()]
|
|
impl FruitTree for BananaTree {
|
|
fn shake(&self, shakes: u32) -> Vec<Fruit>{
|
|
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.
|