#edn #interop #serialization #deprecated #emit #parse #data

废弃 无需 std edn-rs

[已废弃]:用于解析和输出 EDN 的包

76 个版本

0.18.0 2024 年 6 月 15 日
0.17.5 2023 年 12 月 16 日
0.17.4 2022 年 5 月 28 日
0.17.1 2022 年 2 月 17 日
0.1.0 2019 年 11 月 27 日

#edn 中排名 12

Download history 20/week @ 2024-05-04 14/week @ 2024-05-11 24/week @ 2024-05-18 26/week @ 2024-05-25 35/week @ 2024-06-01 40/week @ 2024-06-08 282/week @ 2024-06-15 80/week @ 2024-06-22 61/week @ 2024-06-29 45/week @ 2024-07-06 15/week @ 2024-07-13 84/week @ 2024-07-20 350/week @ 2024-07-27 18/week @ 2024-08-03 22/week @ 2024-08-10 5/week @ 2024-08-17

每月下载量 403
用于 5 个包

MIT 许可协议

125KB
2.5K SLoC

废弃警告

该项目目前开发已暂停。没有新功能正在开发中,也没有破坏性更改。如果您有关键问题,我们可能会查看。您可能发现 Grinkers/clojure-reader 作为合适的替代品,它是由我们的维护者 @Grinkers 构建的。

edn-rs

Build Status codecov

用于解析和输出 EDN 的包 (Extensible Data Notation)

  • MSRV(最低支持的 Rust 版本)是稳定版减去 2 个版本。一旦稳定(1.0.0),计划无限期维护 MSRV。
  • 当前库维护者:Kevin Nakamura (@Grinkers)

完整集成示例

用法

默认

包含功能 stdsets

[dependencies]
edn-rs = "0.17.4"

no_std

要使用 edn-rs 而不带任何其他依赖项,请禁用默认功能。 edn-rs 仍然依赖于 alloc。在 no_std 环境中,您必须提供自己的 #[global_allocator]

[dependencies]
edn-rs = { version = "0.17.4", default-features = false }

可选功能

  • std:实现 Hashmap 和 HashSet 的序列化和反序列化;还包含一些浮点功能。
  • sets:实现 EDN 集的序列化和反序列化。依赖于 ordered-float
  • json:实现 json→edn 和 edn→json 转换。依赖于 regex

快速参考

使用 edn! 宏解析 EDN 令牌为 Edn

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".to_string()),
                Edn::Double(1.2.into()),
                Edn::Int(3),
                Edn::Bool(false),
                Edn::Key(":f".to_string()),
                Edn::Nil,
                Edn::Rational("3/4".to_string())
            ]
        )
    );

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

使用 Edn::from_str 解析 EDN 字符串

use edn_rs::{
    set, map,
    Edn, Map, Vector, Set,
};
use std::str::FromStr;

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

要遍历 Edn 数据,可以使用 getget_mut

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()));
}

使用 ednderive::Serialize 将 Rust 类型序列化为 EDN

use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use edn_rs::{
   map, set, hmap, hset
};
use edn_derive::Serialize;

#[derive(Debug, Clone, Serialize)]
struct ExampleEdn {
   btreemap: BTreeMap<String, Vec<String>>,
   btreeset: BTreeSet<i64>,
   hashmap: HashMap<String, Vec<String>>,
   hashset: HashSet<i64>,
   tuples: (i32, bool, char),
   nothing: (),
}

fn main() {
   let edn = ExampleEdn {
       btreemap: map!{"this is a key".to_string() => vec!["with".to_string(), "many".to_string(), "keys".to_string()]},
       btreeset: set!{3i64, 4i64, 5i64},
       hashmap: hmap!{"this is a key".to_string() => vec!["with".to_string(), "many".to_string(), "keys".to_string()]},
       hashset: hset!{3i64},
       tuples: (3i32, true, 'd'),
       nothing: (),
   };

   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), :nothing nil, }
}

将字符串反序列化为 Rust 类型:

目前,您必须自己实现 Deserialize 特性。不久的将来,您将通过 edn-derive 包自动实现。

use edn_rs::{Deserialize, Edn, EdnError};

#[derive(Debug, PartialEq)]
struct Person {
   name: String,
   age: u64,
}

impl Deserialize for Person {
   fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
       Ok(Self {
           name: edn_rs::from_edn(&edn[":name"])?,
           age: edn_rs::from_edn(&edn[":age"])?,
       })
   }
}

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

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

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

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

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

   Ok(())
}

将 EDN 类型反序列化为 Rust 类型:

  • 将反序列化到 std::collections::* 是当前不安全的。

目前,您必须自己实现 Deserialize 特性。不久的将来,您将通过 edn-derive 包自动实现。

use edn_rs::{map, Deserialize, Edn, EdnError, Map};

#[derive(Debug, PartialEq)]
struct Person {
   name: String,
   age: u64,
}

impl Deserialize for Person {
   fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
       Ok(Self {
           name: edn_rs::from_edn(&edn[":name"])?,
           age: edn_rs::from_edn(&edn[":age"])?,
       })
   }
}

fn main() -> Result<(), EdnError> {
   let edn = Edn::Map(Map::new(map! {
       ":name".to_string() => Edn::Str("rose".to_string()),
       ":age".to_string() => Edn::UInt(66)
   }));
   let person: Person = edn_rs::from_edn(&edn)?;

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

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

   let bad_edn = Edn::Map(Map::new(map! {
       ":name".to_string() => Edn::Str("rose".to_string()),
       ":age".to_string() => Edn::Str("some text".to_string())
   }));
   let person: Result<Person, EdnError> = edn_rs::from_edn(&bad_edn);

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

   Ok(())
}

从 Json 发射 EDN 格式

  • 此函数需要激活 json 功能。要启用此功能,请将以下行添加到您的 Cargo.toml 依赖项中:edn-rs = { version = "0.17.4", features = ["json"] }
use edn_rs::json_to_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": "eva",
                   "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 \"eva\", :age 22 }, { :name \"Julia\", :age 32.0 } ], :country-or-origin \"Brazil\", :queerentener true, :brain nil }"
}

从类型 edn_rs::Edn 发射 JSON

  • 关联方法是 to_json,它需要激活 json 功能。要启用此功能,请将以下行添加到您的 Cargo.toml 依赖项中:edn-rs = { version = "0.17.4", features = ["json"] }
use std::str::FromStr;
fn complex_json() {
    let edn = "{
        :people-list [
            { :first-name \"eva\", :age 22 },
            { :first-name \"Julia\", :age 32.0 }
        ],
        :country-or-origin \"Brazil\",
        :queerentener true,
        :brain nil }";
    let parsed_edn : edn_rs::Edn = edn_rs::Edn::from_str(edn).unwrap();
    let actual_json = parsed_edn.to_json();
    let expected = String::from(
        "{\"brain\": null,
          \"countryOrOrigin\": \"Brazil\",
          \"peopleList\": [
              {\"age\": 22, \"firstName\": \"eva\"},
              {\"age\": 32.0, \"firstName\": \"Julia\"}
            ],
          \"queerentener\": true}",
    );
    assert_eq!(
        actual_json,
        expected
    );
}

to_string/to_debug

to_debug 发射 Edn 类型的 Debug 版本。

use edn_rs::edn::{Edn, Vector};

let edn = Edn::Vector(Vector::new(vec![Edn::Int(5), Edn::Int(6), Edn::Int(7)]));
let expected = "Vector(Vector([Int(5), Int(6), Int(7)]))";

assert_eq!(edn.to_debug(), expected);

to_string 发射有效的 edn。

use edn_rs::edn::{Edn, Vector};

let edn = Edn::Vector(Vector::new(vec![Edn::Int(5), Edn::Int(6), Edn::Int(7)]));
let expected = "[5, 6, 7, ]";

assert_eq!(edn.to_string(), expected);

Larger to_string example

fn complex_ok() -> Result<(), EdnError> {
    use std::str::FromStr;
    let edn_str = "{ :list [{:name \"rose\" :age 66 :cool true}, {:name \"josh\" :age 33 :cool false}, {:name \"eva\" :age 296 :cool true}] }";

    let edn = Edn::from_str(edn_str)?;
    println!("{:?}", edn.to_string());
    // "{:list: [{:age 66, :cool true, :name \"rose\", }, {:age 33, :cool false, :name \"josh\", }, {:age 296, :cool true, :name \"eva\", }, ], }"

    Ok(())
}

Edn-rs 当前功能

  • 定义 struct 以映射 EDN 信息 EdnNode
  • 定义 EDN 类型,EdnType
    • 将 EDN 类型转换为原始类型:Edn::Bool(true).into() -> true。这是通过 to_floatto_boolto_intto_vec 实现的。
    • Edn 实现 futures::Future 特性
    • Edn 实现 to_string
    • Edn 实现 to_debug
  • 解析 EDN 数据 from_str
    • nil ""
    • 字符串 "\"string\""
    • 数字 "324352""3442.234""3/4"
    • 关键字 :a
    • 符号 sym-bol-s
    • 向量 "[1 :2 \"d\"]"
    • 列表 "(1 :2 \"d\")"
    • 集合 "#{1 2 3}"
    • 映射 "{:a 1 :b 2 }"
    • 标签 #inst \"yyyy-mm-ddTHH:MM:ss\"#uuid \"<some-uuid>\"作为字符串数据(不支持自定义读取器)
    • 嵌套结构 "{:a \"2\" :b [true false] :c #{:A {:a :b} nil}}"
  • 相互嵌套的简单数据结构edn!
    • 向量中的向量 "[1 2 [:3 \"4\"]]"
    • 向量中的集合 "[1 2 #{:3 \"4\"}]"
    • 列表中的列表 "(1 2 (:3 \"4\"))"
    • 列表中的集合 "'#{1 2 (:3 \"4\")}"
    • 一般映射 "{:a 2 :b {:3 \"4\"}}""{:a 2 :b [:3 \"4\"]}"
  • 多个简单数据结构相互嵌套(向量中的映射和集合)
  • 多层嵌套数据结构(列表中的向量中的向量中的集合中的映射)
  • 通过 Edn 数据导航
    • 通过集合导航。通过set_iter实现
  • JSON 到 Edn
    • JSON 字符串到 EDN 字符串
    • 宏处理结构体和枚举到 EDN
  • 特质 Deserialize EDN 到结构体
  • 特质 Serialize 结构体到 EDN

edn-derive

edn-derive 是一个用于序列化和反序列化 Edn 值的 proc-macro 库,目前处于 测试版 阶段,可以在 crates.iogithub 找到。

用法

只需将以下内容添加到您的 Cargo.toml 文件中:

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

示例

序列化

use edn_derive::Serialize;

#[derive(Serialize)]
pub struct Person {
    name: String,
    age: u64,
}

fn main() {
    let person = Person {
        name: "joana".to_string(),
        age: 290000,
    };
    assert_eq!(
        edn_rs::to_string(person),
        "{ :name \"joana\", :age 290000, }"
    );
}

反序列化

use edn_derive::Deserialize;
use edn_rs::EdnError;

// The `Debug` and `PartialEq` are only necessary because of `assert_eq`, you don't need them
#[derive(Deserialize, Debug, PartialEq)]
pub struct Person {
    name: String,
    age: u64,
}

fn main() -> Result<(), EdnError> {
    let edn_person = "{ :name \"joana\", :age 290000, }";

    let person: Person = edn_rs::from_str(edn_person)?;

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

    Ok(())
}

当前功能

  • derive Serialize
  • edn_rs::to_string
  • derive Deserialize
  • letval:YourStruct= edn_rs::from_str(&str)

依赖

~0–540KB