edn-rs

Near Stable

Crate to parse and emit EDN Build Status * This lib does not make effort to conform the EDN received to EDN Spec. The lib that generated this EDN should be responsible for this. For more information on Edn Spec please visit: https://github.com/edn-format/edn.

Current example usage in: * crate transistor; * atm-crux;

Usage

Cargo.toml toml [dependencies] edn-rs = "0.12.1"

Parse an EDN token into a Edn with edn! macro: ```rust use edn_rs::{ edn, Edn, List };

fn main() { let edn = edn!((sym 1.2 3 false :f nil 3/4)); let expected = Edn::List( List::new( vec![ Edn::Symbol("sym".tostring()), Edn::Double(1.2.into()), Edn::Int(3), Edn::Bool(false), Edn::Key("f".tostring()), Edn::Nil, Edn::Rational("3/4".to_string()) ] ) );

println!("{:?}", edn);
assert_eq!(edn, expected);

} ```

Parse an EDN String with Edn::from_str: ```rust use edn_rs::{ set, map, Edn, Map, Vector, Set, }; use std::str::FromStr;

fn main() -> Result<(), String> { let ednstr = "{:a \"2\" :b [true false] :c #{:A {:a :b} nil}}"; // std::str::FromStr let edn = Edn::fromstr(edn_str);

assert_eq!(
    edn,
    Edn::Map(Map::new(
        map!{
            ":a".to_string() => Edn::Str("2".to_string()),
            ":b".to_string() => Edn::Vector(Vector::new(vec![Edn::Bool(true), Edn::Bool(false)])),
            ":c".to_string() => Edn::Set(Set::new(
                set!{
                    Edn::Map(Map::new(map!{":a".to_string() => Edn::Key(":b".to_string())})),
                    Edn::Key(":A".to_string()),
                    Edn::Nil}))}
    ))
);

assert_eq!(edn[":b"][0], Edn::Bool(true));

Ok(())

} ```

To navigate through Edn data you can just use get and get_mut:

```rust use edn_rs::{ edn, Edn, List, Map };

fn main() { let edn = edn!((sym 1.2 3 {false :f nil 3/4}));

println!("{:?}", edn);
assert_eq!(edn[1], edn!(1.2));
assert_eq!(edn[1], Edn::Double(1.2f64.into()));
assert_eq!(edn[3]["false"], edn!(:f));
assert_eq!(edn[3]["false"], Edn::Key("f".to_string()));

} ```

Serializes Rust Types into EDN with ser_struct! ```rust use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use ednrs::{ serstruct, map, set, hmap, hset };

fn main() { serstruct!{ #[derive(Debug, Clone)] struct Edn { btreemap: BTreeMap>, btreeset: BTreeSet, hashmap: HashMap>, hashset: HashSet, tuples: (i32, bool, char), } }; let edn = Edn { btreemap: map!{"this is a key".tostring() => vec!["with".tostring(), "many".tostring(), "keys".tostring()]}, btreeset: set!{3i64, 4i64, 5i64}, hashmap: hmap!{"this is a key".tostring() => vec!["with".tostring(), "many".tostring(), "keys".to_string()]}, hashset: hset!{3i64}, tuples: (3i32, true, 'd') };

println!("{}", edn_rs::to_string(edn));
// { :btreemap {:this-is-a-key [\"with\", \"many\", \"keys\"]}, :btreeset #{3, 4, 5}, :hashmap {:this-is-a-key [\"with\", \"many\", \"keys\"]}, :hashset #{3}, :tuples (3, true, \\d), }

} ```

Deserializes Strings into Rust Types:

For now you have to implement the conversion yourself with the Deserialize trait. Soon you'll be able to have that implemented for you via edn-derive crate. ```rust use edn_rs::{Deserialize, Edn, EdnError};

[derive(Debug, PartialEq)]

struct Person { name: String, age: usize, }

impl Deserialize for Person { fn deserialize(edn: Edn) -> Result { Ok(Self { name: edn[":name"].tostring(), age: edn[":age"].touint().okorelse(|| { EdnError::Deserialize("couldn't convert :age into uint".to_string()) })?, }) } }

fn main() -> Result<(), EdnError> { let ednstr = "{:name \"rose\" :age 66}"; let person: Person = ednrs::fromstr(ednstr)?;

assert_eq!(
    person,
    Person {
        name: "rose".to_string(),
        age: 66,
    }
);

println!("{:?}", person);
// Person { name: "rose", age: 66 }

let bad_edn_str = "{:name \"rose\" :age \"not an uint\"}";
let person: Result<Person, EdnError> = edn_rs::from_str(bad_edn_str);

assert_eq!(
    person,
    Err(EdnError::Deserialize(
        "couldn't convert `:age` into `uint`".to_string()
    ))
);

Ok(())

} ```

Emits EDN format from a Json: * This function requires feature json to be activated. To enable this feature add to your Cargo.toml dependencies the following line edn-rs = { version = 0.12.1", features = ["json"] }.

```rust use ednrs::jsonto_edn;

fn main() { let json = String::from(r#"{"hello": "world"}"#); let edn = String::from(r#"{:hello "world"}"#);

println!("{:?}", json_to_edn(json.clone()));
assert_eq!(edn, json_to_edn(json));

let complex_json = String::from(r#"{
        "people": 
        [
            {
                "name": "otavio",
                "age": 22
            },
            {
                "name": "Julia",
                "age": 32.0
            }
        ],
        "country or origin": "Brazil",
        "queerentener": true,
        "brain": null
    }"#);

println!("{:?}", json_to_edn(complex_json.clone()).replace("  ", "").replace("\n", " "));
// "{ :people  [ { :name \"otavio\", :age 22 }, { :name \"Julia\", :age 32.0 } ], :country-or-origin \"Brazil\", :queerentener true, :brain nil }"

} ```

Using async/await with Edn type

Edn supports futures by using the feature async. To enable this feature add to your Cargo.toml dependencies the following line edn-rs = { version = 0.12.1", features = ["async"] } and you can use futures as in the following example.

```rust use edn_rs::{edn, Double, Edn, Vector}; use futures::prelude::; use futures::Future; use tokio::prelude::;

async fn foo() -> impl Future + Send { edn!([1 1.5 "hello" :key]) }

[tokio::main]

async fn main() { let edn = foo().await.await;

println!("{}", edn.to_string());
assert_eq!(edn, edn!([1 1.5 "hello" :key]));

assert_eq!(edn[1].to_float(), Some(1.5f64));

} ```

Edn-rs Current Features

edn-derive

edn-derive is a proc-macro crate to (De)serialize Edn values, currently it is pre-alpha and it can be found at crates.io or at github.

Usage

Just add to your Cargo.toml the following:

toml [dependencies] edn-derive = "<version>" edn-rs = "0.12.1"

Examples

Serialize ```rust use edn_derive::Serialize;

[derive(Serialize)]

pub struct Person { name: String, age: usize, }

fn main() { let person = Person { name: "joana".tostring(), age: 290000, }; asserteq!( ednrs::tostring(person), "{ :name \"joana\", :age 290000, }" ); } ```

Current Features