pub trait Serialize {
fn serialize(self) -> String;
}
#[doc(hidden)]
#[must_use]
pub fn field_names(id: Vec<String>) -> std::collections::HashMap<String, String> {
let mut hashmap = std::collections::HashMap::new();
for i in id {
let mut value = i.replace("___", "/").replace("__", ".").replace('_', "-");
value.insert(0, ':');
hashmap.insert(i.to_string(), value);
}
hashmap
}
macro_rules! ser_primitives {
( $( $name:ty ),+ ) => {
$(
impl Serialize for $name
{
fn serialize(self) -> String {
format!("{:?}", self)
}
}
)+
};
}
impl<T> Serialize for Vec<T>
where
T: Serialize,
{
fn serialize(self) -> String {
let aux_vec = self
.into_iter()
.map(Serialize::serialize)
.collect::<Vec<String>>();
let mut s = String::new();
s.push('[');
s.push_str(&aux_vec.join(", "));
s.push(']');
s
}
}
#[allow(clippy::implicit_hasher)]
impl<T> Serialize for std::collections::HashSet<T>
where
T: Serialize,
{
fn serialize(self) -> String {
let aux_vec = self
.into_iter()
.map(Serialize::serialize)
.collect::<Vec<String>>();
let mut s = String::new();
s.push('#');
s.push('{');
s.push_str(&aux_vec.join(", "));
s.push('}');
s
}
}
impl<T> Serialize for std::collections::BTreeSet<T>
where
T: Serialize,
{
fn serialize(self) -> String {
let aux_vec = self
.into_iter()
.map(Serialize::serialize)
.collect::<Vec<String>>();
let mut s = String::new();
s.push('#');
s.push('{');
s.push_str(&aux_vec.join(", "));
s.push('}');
s
}
}
impl<T> Serialize for std::collections::LinkedList<T>
where
T: Serialize,
{
fn serialize(self) -> String {
let aux_vec = self
.into_iter()
.map(Serialize::serialize)
.collect::<Vec<String>>();
let mut s = String::new();
s.push('(');
s.push_str(&aux_vec.join(", "));
s.push(')');
s
}
}
#[allow(clippy::implicit_hasher)]
impl<T> Serialize for std::collections::HashMap<String, T>
where
T: Serialize,
{
fn serialize(self) -> String {
let aux_vec = self
.into_iter()
.map(|(k, v)| {
format!(
":{} {}",
k.replace(' ', "-").replace('_', "-"),
v.serialize()
)
})
.collect::<Vec<String>>();
let mut s = String::new();
s.push('{');
s.push_str(&aux_vec.join(", "));
s.push('}');
s
}
}
#[allow(clippy::implicit_hasher)]
impl<T> Serialize for std::collections::HashMap<&str, T>
where
T: Serialize,
{
fn serialize(self) -> String {
let aux_vec = self
.into_iter()
.map(|(k, v)| {
format!(
":{} {}",
k.replace(' ', "-").replace('_', "-"),
v.serialize()
)
})
.collect::<Vec<String>>();
let mut s = String::new();
s.push('{');
s.push_str(&aux_vec.join(", "));
s.push('}');
s
}
}
impl<T> Serialize for std::collections::BTreeMap<String, T>
where
T: Serialize,
{
fn serialize(self) -> String {
let aux_vec = self
.into_iter()
.map(|(k, v)| {
format!(
":{} {}",
k.replace(' ', "-").replace('_', "-"),
v.serialize()
)
})
.collect::<Vec<String>>();
let mut s = String::new();
s.push('{');
s.push_str(&aux_vec.join(", "));
s.push('}');
s
}
}
impl<T> Serialize for std::collections::BTreeMap<&str, T>
where
T: Serialize,
{
fn serialize(self) -> String {
let aux_vec = self
.into_iter()
.map(|(k, v)| {
format!(
":{} {}",
k.to_string().replace(' ', "-").replace('_', "-"),
v.serialize()
)
})
.collect::<Vec<String>>();
let mut s = String::new();
s.push('{');
s.push_str(&aux_vec.join(", "));
s.push('}');
s
}
}
ser_primitives![i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64, bool];
impl Serialize for () {
fn serialize(self) -> String {
"nil".to_string()
}
}
impl Serialize for String {
fn serialize(self) -> String {
format!("{:?}", self)
}
}
impl Serialize for &str {
fn serialize(self) -> String {
format!("{:?}", self)
}
}
impl Serialize for char {
fn serialize(self) -> String {
format!("\\{}", self)
}
}
impl<T> Serialize for Option<T>
where
T: Serialize,
{
fn serialize(self) -> String {
if let Some(t) = self {
t.serialize()
} else {
String::from("nil")
}
}
}
impl<A: Serialize> Serialize for (A,) {
fn serialize(self) -> String {
format!("({})", self.0.serialize())
}
}
impl<A: Serialize, B: Serialize> Serialize for (A, B) {
fn serialize(self) -> String {
format!("({}, {})", self.0.serialize(), self.1.serialize())
}
}
impl<A: Serialize, B: Serialize, C: Serialize> Serialize for (A, B, C) {
fn serialize(self) -> String {
format!(
"({}, {}, {})",
self.0.serialize(),
self.1.serialize(),
self.2.serialize()
)
}
}
impl<A: Serialize, B: Serialize, C: Serialize, D: Serialize> Serialize for (A, B, C, D) {
fn serialize(self) -> String {
format!(
"({}, {}, {}, {})",
self.0.serialize(),
self.1.serialize(),
self.2.serialize(),
self.3.serialize()
)
}
}
impl<A: Serialize, B: Serialize, C: Serialize, D: Serialize, E: Serialize> Serialize
for (A, B, C, D, E)
{
fn serialize(self) -> String {
format!(
"({}, {}, {}, {}, {})",
self.0.serialize(),
self.1.serialize(),
self.2.serialize(),
self.3.serialize(),
self.4.serialize()
)
}
}
impl<A: Serialize, B: Serialize, C: Serialize, D: Serialize, E: Serialize, F: Serialize> Serialize
for (A, B, C, D, E, F)
{
fn serialize(self) -> String {
format!(
"({}, {}, {}, {}, {}, {})",
self.0.serialize(),
self.1.serialize(),
self.2.serialize(),
self.3.serialize(),
self.4.serialize(),
self.5.serialize()
)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn unit() {
assert_eq!(().serialize(), "nil");
}
#[test]
fn primitive_types() {
let i = -34i32;
assert_eq!(i.serialize(), String::from("-34"));
assert_eq!('c'.serialize(), String::from("\\c"));
assert_eq!(8i8.serialize(), String::from("8"));
assert_eq!(8i16.serialize(), String::from("8"));
assert_eq!(8i32.serialize(), String::from("8"));
assert_eq!(8i64.serialize(), String::from("8"));
assert_eq!(8isize.serialize(), String::from("8"));
assert_eq!(128u8.serialize(), String::from("128"));
assert_eq!(128u16.serialize(), String::from("128"));
assert_eq!(128u32.serialize(), String::from("128"));
assert_eq!(128u64.serialize(), String::from("128"));
assert_eq!(128usize.serialize(), String::from("128"));
assert_eq!(true.serialize(), String::from("true"));
}
#[test]
fn tuples() {
let t2 = (12i32, 3.5f32);
let t3 = (12i32, 3.5f32, "oi");
let t4 = (12i32, 3.5f32, "oi", 'd');
assert_eq!(t2.serialize(), "(12, 3.5)");
assert_eq!(t3.serialize(), "(12, 3.5, \"oi\")");
assert_eq!(t4.serialize(), "(12, 3.5, \"oi\", \\d)");
}
#[test]
fn vectors() {
let v_i8 = vec![3i8, 12i8, 24i8, 72i8];
let v_u16 = vec![3u16, 12u16, 24u16, 72u16];
let v_f32 = vec![3.0f32, 12.1f32, 24.2f32, 72.3f32];
let v_i64 = vec![3i64, 12i64, 24i64, 72i64];
let v_usize = vec![3usize, 12usize, 24usize, 72usize];
let v_bool = vec![true, false];
assert_eq!(v_i8.serialize(), "[3, 12, 24, 72]");
assert_eq!(v_u16.serialize(), "[3, 12, 24, 72]");
assert_eq!(v_f32.serialize(), "[3.0, 12.1, 24.2, 72.3]");
assert_eq!(v_i64.serialize(), "[3, 12, 24, 72]");
assert_eq!(v_usize.serialize(), "[3, 12, 24, 72]");
assert_eq!(v_bool.serialize(), "[true, false]")
}
#[test]
fn literals_vec() {
let v_str = vec!["aba", "cate", "azul"];
let v_string = vec!["aba".to_string(), "cate".to_string(), "azul".to_string()];
assert_eq!(v_str.serialize(), "[\"aba\", \"cate\", \"azul\"]");
assert_eq!(v_string.serialize(), "[\"aba\", \"cate\", \"azul\"]");
}
#[test]
fn hashsets() {
use std::collections::HashSet;
let set_i8 = (vec![3i8, 12i8, 24i8, 72i8]
.into_iter()
.collect::<HashSet<i8>>())
.serialize();
let set_u16 = (vec![3u16, 12u16, 24u16, 72u16]
.into_iter()
.collect::<HashSet<u16>>())
.serialize();
let set_i64 = (vec![3i64, 12i64, 24i64, 72i64]
.into_iter()
.collect::<HashSet<i64>>())
.serialize();
let set_bool = (vec![true, false].into_iter().collect::<HashSet<bool>>()).serialize();
let set_str = (vec!["aba", "cate", "azul"]
.into_iter()
.collect::<HashSet<&str>>())
.serialize();
let set_string = (vec!["aba".to_string(), "cate".to_string(), "azul".to_string()]
.into_iter()
.collect::<HashSet<String>>())
.serialize();
assert!(
set_i8.contains("#{")
&& set_i8.contains(",")
&& set_i8.contains("3")
&& set_i8.contains("}")
);
assert!(
set_u16.contains("#{")
&& set_u16.contains(",")
&& set_u16.contains("3")
&& set_u16.contains("}")
);
assert!(
set_i64.contains("#{")
&& set_i64.contains(",")
&& set_i64.contains("3")
&& set_i64.contains("}")
);
assert!(
set_bool.contains("#{")
&& set_bool.contains(",")
&& set_bool.contains("true")
&& set_bool.contains("false")
&& set_bool.contains("}")
);
assert!(
set_str.contains("#{")
&& set_str.contains(",")
&& set_str.contains("\"aba\"")
&& set_str.contains("\"cate\"")
&& set_str.contains("}")
);
assert!(
set_string.contains("#{")
&& set_string.contains(",")
&& set_string.contains("\"aba\"")
&& set_string.contains("\"cate\"")
&& set_string.contains("}")
);
}
#[test]
fn btreesets() {
use std::collections::BTreeSet;
let set_i8 = (vec![3i8, 12i8, 24i8, 72i8]
.into_iter()
.collect::<BTreeSet<i8>>())
.serialize();
let set_u16 = (vec![3u16, 12u16, 24u16, 72u16]
.into_iter()
.collect::<BTreeSet<u16>>())
.serialize();
let set_i64 = (vec![3i64, 12i64, 24i64, 72i64]
.into_iter()
.collect::<BTreeSet<i64>>())
.serialize();
let set_bool = (vec![true, false].into_iter().collect::<BTreeSet<bool>>()).serialize();
let set_str = (vec!["aba", "cate", "azul"]
.into_iter()
.collect::<BTreeSet<&str>>())
.serialize();
let set_string = (vec!["aba".to_string(), "cate".to_string(), "azul".to_string()]
.into_iter()
.collect::<BTreeSet<String>>())
.serialize();
assert!(
set_i8.contains("#{")
&& set_i8.contains(",")
&& set_i8.contains("3")
&& set_i8.contains("}")
);
assert!(
set_u16.contains("#{")
&& set_u16.contains(",")
&& set_u16.contains("3")
&& set_u16.contains("}")
);
assert!(
set_i64.contains("#{")
&& set_i64.contains(",")
&& set_i64.contains("3")
&& set_i64.contains("}")
);
assert!(
set_bool.contains("#{")
&& set_bool.contains(",")
&& set_bool.contains("true")
&& set_bool.contains("false")
&& set_bool.contains("}")
);
assert!(
set_str.contains("#{")
&& set_str.contains(",")
&& set_str.contains("\"aba\"")
&& set_str.contains("\"cate\"")
&& set_str.contains("}")
);
assert!(
set_string.contains("#{")
&& set_string.contains(",")
&& set_string.contains("\"aba\"")
&& set_string.contains("\"cate\"")
&& set_string.contains("}")
);
}
#[test]
fn lists() {
use std::collections::LinkedList;
let list_i8 = (vec![3i8, 12i8, 24i8, 72i8]
.into_iter()
.collect::<LinkedList<i8>>())
.serialize();
let list_u16 = (vec![3u16, 12u16, 24u16, 72u16]
.into_iter()
.collect::<LinkedList<u16>>())
.serialize();
let list_i64 = (vec![3i64, 12i64, 24i64, 72i64]
.into_iter()
.collect::<LinkedList<i64>>())
.serialize();
let list_f64 = (vec![3.1f64, 12.2f64, 24.3f64, 72.4f64]
.into_iter()
.collect::<LinkedList<f64>>())
.serialize();
let list_bool = (vec![true, false].into_iter().collect::<LinkedList<bool>>()).serialize();
let list_str = (vec!["aba", "cate", "azul"]
.into_iter()
.collect::<LinkedList<&str>>())
.serialize();
let list_string = (vec!["aba".to_string(), "cate".to_string(), "azul".to_string()]
.into_iter()
.collect::<LinkedList<String>>())
.serialize();
assert_eq!(list_i8, "(3, 12, 24, 72)");
assert_eq!(list_u16, "(3, 12, 24, 72)");
assert_eq!(list_i64, "(3, 12, 24, 72)");
assert_eq!(list_f64, "(3.1, 12.2, 24.3, 72.4)");
assert_eq!(list_bool, "(true, false)");
assert_eq!(list_str, "(\"aba\", \"cate\", \"azul\")");
assert_eq!(list_string, "(\"aba\", \"cate\", \"azul\")");
}
#[test]
fn hashmap() {
let m_i64 = map! {"hello world" => 5i64, "bye_bye" => 125i64}.serialize();
let m_bool =
map! {"hello world".to_string() => true, "bye_bye".to_string() => false}.serialize();
let m_str = map!{"hello world".to_string() => "this is str 1", "bye_bye".to_string() => "this is str 2"}.serialize();
assert!(
m_i64.contains(":hello-world 5")
&& m_i64.contains(":bye-bye 125")
&& m_i64.contains("{")
&& m_i64.contains("}")
);
assert!(
m_bool.contains(":hello-world true")
&& m_bool.contains(":bye-bye false")
&& m_bool.contains("{")
&& m_bool.contains("}")
);
assert!(
m_str.contains(":hello-world \"this is str 1\"")
&& m_str.contains(":bye-bye \"this is str 2\"")
&& m_str.contains("{")
&& m_str.contains("}")
);
}
#[test]
fn multi_sized_tuples() {
assert_eq!((1,).serialize(), "(1)");
assert_eq!((1, "cool").serialize(), "(1, \"cool\")");
assert_eq!((1, "cool", false).serialize(), "(1, \"cool\", false)");
assert_eq!(
(1, "cool", false, 'z').serialize(),
"(1, \"cool\", false, \\z)"
);
assert_eq!(
(1, "cool", false, 'z', None::<String>).serialize(),
"(1, \"cool\", false, \\z, nil)"
);
}
}