Skip to content

Instantly share code, notes, and snippets.

@fero23
Created February 13, 2016 04:37
Show Gist options
  • Save fero23/be77ca26cf301bb77379 to your computer and use it in GitHub Desktop.
Save fero23/be77ca26cf301bb77379 to your computer and use it in GitHub Desktop.
Rust macro to create a JS value
use std::collections::HashMap;
use std::convert::From;
enum JsType {
JsNum(i32),
JsString(String),
JsNullable(Option<Box<JsType>>),
JsObject {data: HashMap<String, JsType>, level: u32}
}
impl JsType {
fn to_string(&self) -> String {
use JsType::*;
match self {
&JsNum(ref n) => n.to_string(),
&JsString(ref s) => format!("\"{}\"", s),
&JsNullable(Some(ref jsval)) => jsval.to_string(),
&JsNullable(None) => "null".to_string(),
&JsObject {ref data, ref level} => {
let mut res = String::new();
macro_rules! insert_tab {
() => {
for _ in 0..*level{
res.push('\t');
}
}
}
res.push('{');
for (index, (key, val)) in data.iter().enumerate() {
res.push('\n');
insert_tab!();
res.push_str(
&format!("\t\"{}\" : {}{}", key, val.to_string(),
if data.len() - 1 == index {""} else {","})
);
}
res.push('\n');
insert_tab!();
res.push_str("}");
res
}
}
}
}
impl<'a> From<&'a str> for JsType {
fn from(s: &'a str) -> Self {
JsType::JsString(s.to_string())
}
}
impl From<i32> for JsType {
fn from(n: i32) -> Self {
JsType::JsNum(n)
}
}
impl From<Option<i32>> for JsType {
fn from(nullable: Option<i32>) -> Self {
JsType::JsNullable(nullable.map(|n| Box::new(JsType::from(n))))
}
}
impl<'a> From<Option<&'a str>> for JsType {
fn from(nullable: Option<&'a str>) -> Self {
JsType::JsNullable(nullable.map(|s| Box::new(JsType::from(s))))
}
}
macro_rules! js_object {
{$($key: ident:$val:expr),*} => {{
let mut map = HashMap::new();
$(
let mut jsval = JsType::from($val);
if let JsType::JsObject {ref mut level, ..} = jsval {
*level += 1;
}
map.insert(stringify!($key).to_string(), jsval);
)*;
JsType::JsObject {data: map, level: 0}
}}
}
fn main() {
let object = js_object!{
string: "outer",
num: 1,
inner_object: js_object! {
string: "inner",
num: 2
},
nullable: Some(1),
empty: None::<i32>
};
println!("{}", object.to_string());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment