1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
#![no_std]
#![recursion_limit = "512"]
#[macro_use]
mod macros;
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
use alloc::string::String;
/// Edn type implementation
pub mod edn;
/// Serialization module for most possible types.
/// Tuples are limited between `(A, B)` and `(A, B, C, D, E, F)`, any other tuple needs to be implemented by the `trait Serialize`.
/// This module requires `#[macro_use]` for `structs`.
///
/// Example:
/// ```rust
/// use std::collections::{BTreeMap, BTreeSet};
/// use edn_derive::Serialize;
/// use edn_rs::{set, map, edn::Edn};
///
/// #[derive(Serialize)]
/// struct ExampleEdn {
/// map: BTreeMap<String, Vec<String>>,
/// set: BTreeSet<i64>,
/// tuples: (i32, bool, char),
/// }
/// fn main() {
/// let edn = ExampleEdn {
/// map: map!{"this is a key".to_string() => vec!["with".to_string(), "many".to_string(), "keys".to_string()]},
/// set: set!{3i64, 4i64, 5i64},
/// tuples: (3i32, true, 'd')
/// };
/// println!("{}", edn_rs::to_string(&edn));
/// // { :map {:this-is-a-key ["with", "many", "keys"]}, :set #{3, 4, 5}, :tuples (3, true, \d), }
/// }
///```
#[allow(clippy::needless_doctest_main)]
pub mod serialize;
#[cfg(feature = "json")]
pub(crate) mod json;
#[cfg(feature = "json")]
use alloc::borrow::Cow;
#[cfg(feature = "json")]
use alloc::string::ToString;
mod deserialize;
/// `json_to_edn` receives a json string and parses its common key-values to a regular EDN format. It requires feature `json`
/// tested examples are:
/// 1. `"{\"hello world\": \"julia\"}"` becomes `"{:hello-world \"julia\"}"`
/// 2. `"{\"hello\": null}"` becomes `"{:hello nil}"`
/// 3. `{\"hello\": 'c'}` becomes `"{:hello \\c}"`
/// 4. `"{\"multi_string with underscore\": 545643}"` becomes `"{:multi-string-with-underscore 545643}"`
///
/// ```
/// use edn_rs::json_to_edn;
///
/// fn emits_helloworld_edn() {
/// let json = String::from("{\"hello\": \"world\"}");
/// let edn = String::from("{:hello \"world\"}");
///
/// assert_eq!(edn, json_to_edn(json));
/// }
///
/// fn emits_vec_of_map_edn() {
/// let json = String::from("[{\"hello\": \"world\"}, {\"hello\": \"julia\"}, {\"hello\": \"serde\"}");
/// let edn = String::from("[{:hello \"world\"} {:hello \"julia\"} {:hello \"serde\"}]");
///
/// assert_eq!(edn, json_to_edn(json));
/// }
/// ```
#[cfg(feature = "json")]
#[allow(clippy::missing_panics_doc)] // Our regex's don't rely on user-input
pub fn json_to_edn<'a>(json: impl AsRef<str>) -> Cow<'a, str> {
use regex::{Captures, Regex};
// Convert string keys to EDN keywords
let re = Regex::new(r#""\w*(\s\w*)*":"#).unwrap();
let json = re.replace_all(json.as_ref(), |caps: &Captures<'_>| {
let mut rcap = caps[0].replace(['\"', ':'], "").replace(['_', ' '], "-");
rcap.insert(0, ':');
rcap.to_string()
});
// Convert chars
let c_re = Regex::new(r"'.'").unwrap();
let json = c_re.replace_all(&json[..], |caps: &Captures<'_>| {
let mut rcap = caps[0].replace('\'', "");
rcap.insert(0, '\\');
rcap.to_string()
});
json.replace("null", "nil").into()
}
pub use deserialize::{from_edn, from_str, Deserialize};
pub use edn::Error as EdnError;
#[cfg(feature = "sets")]
pub use edn::Set;
pub use edn::{Edn, List, Map, Vector};
pub use serialize::Serialize;
/// Function for converting Rust types into EDN Strings.
/// For it to work, the type must implement the Serialize trait.
/// Use `#[derive(Serialize)]` from `edn-derive` crate.
///
/// Example:
/// ```rust
/// use std::collections::{BTreeMap, BTreeSet};
/// use edn_derive::Serialize;
/// use edn_rs::{set, map, edn::Edn};
///
/// #[derive(Debug, Serialize)]
/// struct ExampleEdn {
/// map: BTreeMap<String, Vec<String>>,
/// set: BTreeSet<i64>,
/// tuples: (i32, bool, char),
/// }
///
/// fn main() {
/// let edn = ExampleEdn {
/// map: map!{"this is a key".to_string() => vec!["with".to_string(), "many".to_string(), "keys".to_string()]},
/// set: set!{3i64, 4i64, 5i64},
/// tuples: (3i32, true, 'd')
/// };
/// println!("{}", edn_rs::to_string(&edn));
/// // { :map {:this-is-a-key ["with", "many", "keys"]}, :set #{3, 4, 5}, :tuples (3, true, \d), }
/// }
///```
#[allow(clippy::needless_doctest_main)]
pub fn to_string<T: Serialize>(t: &T) -> String {
t.serialize()
}