Created
April 8, 2019 17:51
-
-
Save Geal/12a9e77291553cd5da64f6bab6315497 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use gen::GenError; | |
pub trait SerializeFn<I>: Fn(I) -> Result<I, GenError> {} | |
impl<I, F: Fn(I) ->Result<I, GenError>> SerializeFn<I> for F {} | |
pub fn slice<'a, S: 'a + AsRef<[u8]>>(data: S) -> impl SerializeFn<&'a mut [u8]> { | |
let len = data.as_ref().len(); | |
move |out: &'a mut [u8]| { | |
if out.len() < len { | |
Err(GenError::BufferTooSmall(len)) | |
} else { | |
(&mut out[..len]).copy_from_slice(data.as_ref()); | |
Ok(&mut out[len..]) | |
} | |
} | |
} | |
pub fn string<'a, S: 'a+AsRef<str>>(data: S) -> impl SerializeFn<&'a mut [u8]> { | |
let len = data.as_ref().len(); | |
move |out: &'a mut [u8]| { | |
if out.len() < len { | |
Err(GenError::BufferTooSmall(len)) | |
} else { | |
(&mut out[..len]).copy_from_slice(data.as_ref().as_bytes()); | |
Ok(&mut out[len..]) | |
} | |
} | |
} | |
fn pair<F, G, I>(first: F, second: G) -> impl SerializeFn<I> | |
where F: SerializeFn<I>, | |
G: SerializeFn<I> { | |
move |out: I| { | |
let out = first(out)?; | |
second(out) | |
} | |
} | |
pub fn separated_list<'w, F, G, I, V>(sep: F, val: G, values: &'w [V]) -> impl SerializeFn<I> + 'w | |
where F: SerializeFn<I> + 'w, | |
G: Fn(I, &'w V) -> Result<I, GenError> + 'w { | |
move |mut out: I| { | |
if values.is_empty() { | |
Ok(out) | |
} else { | |
out = val(out, &values[0])?; | |
for i in 1..values.len() { | |
out = sep(out)?; | |
out = val(out, &values[i])?; | |
} | |
Ok(out) | |
} | |
} | |
} | |
/* | |
pub fn separated_list2<'a, 'c, 'd, F, G, I, V: 'd, It: Iterator<Item=&'d V>, Arg: Clone+IntoIterator<Item=&'d V, IntoIter=It>>(sep: F, val: G, values: Arg) -> impl SerializeFn<I> | |
where F: SerializeFn<I> + 'a, | |
G: Fn(I, &'d V) -> Result<I, GenError> + 'c { | |
move |mut out: I| { | |
let mut it = values.clone().into_iter(); | |
match it.next() { | |
None => return Ok(out), | |
Some(first) => { | |
out = val(out, &first)?; | |
} | |
} | |
for v in it { | |
out = sep(out)?; | |
out = val(out, &v)?; | |
} | |
Ok(out) | |
} | |
}*/ | |
pub fn separated_list2<'a, 'b, 'c, F, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(sep: F, values: Arg) -> impl SerializeFn<I> + 'a | |
where F: SerializeFn<I> + 'b + 'a, | |
G: SerializeFn<I> + 'c { | |
move |mut out: I| { | |
let mut it = values.clone().into_iter(); | |
match it.next() { | |
None => return Ok(out), | |
Some(first) => { | |
out = first(out)?; | |
} | |
} | |
for v in it { | |
out = sep(out)?; | |
out = v(out)?; | |
} | |
Ok(out) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(test)] | |
extern crate test; | |
#[macro_use] | |
extern crate cookie_factory; | |
#[macro_use] | |
extern crate maplit; | |
use std::str; | |
use std::collections::BTreeMap; | |
use test::Bencher; | |
use cookie_factory::*; | |
#[derive(Clone, Debug, PartialEq)] | |
pub enum JsonValue { | |
Str(String), | |
Boolean(bool), | |
Num(f64), | |
Array(Vec<JsonValue>), | |
Object(BTreeMap<String, JsonValue>), | |
} | |
#[inline(always)] | |
pub fn gen_str<'a, 'b: 'a>(s: &'b str) -> impl SerializeFn<&'a mut [u8]> { | |
move |out: &'a mut [u8]| { | |
let out = string("\"")(out)?; | |
let out = string(s)(out)?; | |
string("\"")(out) | |
} | |
} | |
#[inline(always)] | |
pub fn gen_bool<'a>(b: bool) -> impl SerializeFn<&'a mut [u8]> { | |
if b { | |
string("true") | |
} else { | |
string("false") | |
} | |
} | |
#[inline(always)] | |
pub fn gen_num<'a>(b: f64) -> impl SerializeFn<&'a mut [u8]> { | |
/*move |out: &'a mut [u8]| { | |
let s = format!("{}", b); | |
string(s)(out) | |
}*/ | |
string("1234.56") | |
} | |
pub fn gen_array<'a, 'b: 'a>(arr: &'b [JsonValue]) -> impl SerializeFn<&'a mut [u8]> { | |
move |out: &'a mut [u8]| { | |
let out = string("[")(out)?; | |
let out = separated_list2(string(","), arr.iter().map(gen_json_value))(out)?; | |
string("]")(out) | |
} | |
} | |
pub fn gen_key_value<'a, 'b: 'a>(kv: (&'b String, &'b JsonValue)) -> impl SerializeFn<&'a mut [u8]> { | |
move |out: &'a mut [u8]| { | |
let out = gen_str(kv.0)(out)?; | |
let out = string(":")(out)?; | |
gen_json_value(&kv.1)(out) | |
} | |
} | |
pub fn gen_object<'a, 'b: 'a>(o: &'b BTreeMap<String, JsonValue>) -> impl SerializeFn<&'a mut [u8]> { | |
move |out: &'a mut [u8]| { | |
let out = string("{")(out)?; | |
let out = separated_list2(string(","), o.iter().map(gen_key_value))(out)?; | |
string("}")(out) | |
} | |
} | |
pub fn gen_json_value<'a>(g: &'a JsonValue) -> impl SerializeFn<&'a mut [u8]> { | |
move |out: &'a mut [u8]| { | |
match g { | |
JsonValue::Str(ref s) => gen_str(s)(out), | |
JsonValue::Boolean(ref b) => gen_bool(*b)(out), | |
JsonValue::Num(ref n) => gen_num(*n)(out), | |
JsonValue::Array(ref v) => gen_array(v)(out), | |
JsonValue::Object(ref o) => gen_object(o)(out), | |
} | |
} | |
} | |
use std::iter::repeat; | |
#[test] | |
fn json_test() { | |
let value = JsonValue::Object(btreemap!{ | |
String::from("arr") => JsonValue::Array(vec![JsonValue::Num(1.0), JsonValue::Num(12.3), JsonValue::Num(42.0)]), | |
String::from("b") => JsonValue::Boolean(true), | |
String::from("o") => JsonValue::Object(btreemap!{ | |
String::from("x") => JsonValue::Str(String::from("abcd")), | |
String::from("y") => JsonValue::Str(String::from("efgh")), | |
String::from("empty") => JsonValue::Array(vec![]), | |
}), | |
}); | |
let mut buffer = repeat(0).take(16384).collect::<Vec<u8>>(); | |
let pos = { | |
let mut sr = gen_json_value(&value); | |
let res = sr(&mut buffer).unwrap(); | |
res.as_ptr() as usize | |
}; | |
let index = pos - buffer.as_ptr() as usize; | |
println!("result:\n{}", str::from_utf8(&buffer[..index]).unwrap()); | |
assert_eq!(str::from_utf8(&buffer[..index]).unwrap(), | |
"{\"arr\":[1234.56,1234.56,1234.56],\"b\":true,\"o\":{\"empty\":[],\"x\":\"abcd\",\"y\":\"efgh\"}}"); | |
panic!(); | |
} | |
#[bench] | |
fn combinators_json(b: &mut Bencher) { | |
let element = JsonValue::Object(btreemap!{ | |
String::from("arr") => JsonValue::Array(vec![JsonValue::Num(1.0), JsonValue::Num(12.3), JsonValue::Num(42.0)]), | |
String::from("b") => JsonValue::Boolean(true), | |
String::from("o") => JsonValue::Object(btreemap!{ | |
String::from("x") => JsonValue::Str(String::from("abcd")), | |
String::from("y") => JsonValue::Str(String::from("efgh")), | |
String::from("empty") => JsonValue::Array(vec![]), | |
}), | |
}); | |
let value = JsonValue::Array(repeat(element).take(10).collect::<Vec<JsonValue>>()); | |
let mut buffer = repeat(0u8).take(16384).collect::<Vec<_>>(); | |
let pos = { | |
let mut sr = gen_json_value(&value); | |
let res = sr(&mut buffer).unwrap(); | |
res.as_ptr() as usize | |
}; | |
let index = pos - buffer.as_ptr() as usize; | |
b.bytes = index as u64; | |
b.iter(|| { | |
let mut sr = gen_json_value(&value); | |
let _ = sr(&mut buffer).unwrap(); | |
}); | |
} | |
#[bench] | |
fn combinators_json_create_serializer(b: &mut Bencher) { | |
let element = JsonValue::Object(btreemap!{ | |
String::from("arr") => JsonValue::Array(vec![JsonValue::Num(1.0), JsonValue::Num(12.3), JsonValue::Num(42.0)]), | |
String::from("b") => JsonValue::Boolean(true), | |
String::from("o") => JsonValue::Object(btreemap!{ | |
String::from("x") => JsonValue::Str(String::from("abcd")), | |
String::from("y") => JsonValue::Str(String::from("efgh")), | |
String::from("empty") => JsonValue::Array(vec![]), | |
}), | |
}); | |
let value = JsonValue::Array(repeat(element).take(10).collect::<Vec<JsonValue>>()); | |
b.iter(|| { | |
gen_json_value(&value) | |
}); | |
} | |
#[bench] | |
fn combinators_gen_str_create_serializer(b: &mut Bencher) { | |
let mut buffer = repeat(0).take(16384).collect::<Vec<u8>>(); | |
let pos = { | |
let mut sr = gen_str(&"hello"); | |
let res = sr(&mut buffer).unwrap(); | |
res.as_ptr() as usize | |
}; | |
let index = pos - buffer.as_ptr() as usize; | |
b.bytes = index as u64; | |
b.iter(|| { | |
gen_str(&"hello") | |
}); | |
} | |
#[bench] | |
fn combinators_gen_str(b: &mut Bencher) { | |
let mut buffer = repeat(0).take(16384).collect::<Vec<u8>>(); | |
let pos = { | |
let mut sr = gen_str(&"hello"); | |
let res = sr(&mut buffer).unwrap(); | |
res.as_ptr() as usize | |
}; | |
let index = pos - buffer.as_ptr() as usize; | |
b.bytes = index as u64; | |
b.iter(|| { | |
let mut sr = gen_str(&"hello"); | |
let _ = sr(&mut buffer).unwrap(); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment