Skip to content

Commit

Permalink
(feat) use Rc to wrap data to avoid too much data clone [#166]
Browse files Browse the repository at this point in the history
Signed-off-by: Ning Sun <sunng@about.me>
  • Loading branch information
sunng87 committed Jul 9, 2017
1 parent b2354be commit 288ea1c
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 12 deletions.
18 changes: 8 additions & 10 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::rc::Rc;

use serde::Serialize;
use serde_json::value::{Value as Json, Map, to_value};

Expand All @@ -15,7 +17,7 @@ pub type Object = BTreeMap<String, Json>;
///
#[derive(Debug, Clone)]
pub struct Context {
data: Json,
data: Rc<Json>,
}

#[inline]
Expand Down Expand Up @@ -119,13 +121,13 @@ pub fn merge_json(base: &Json, addition: &Object) -> Json {
impl Context {
/// Create a context with null data
pub fn null() -> Context {
Context { data: Json::Null }
Context { data: Rc::new(Json::Null) }
}

/// Create a context with given data
pub fn wraps<T: Serialize>(e: &T) -> Result<Context, RenderError> {
to_value(e).map_err(RenderError::from).map(|d| {
Context { data: d }
Context { data: Rc::new(d) }
})
}

Expand All @@ -144,7 +146,7 @@ impl Context {
parse_json_visitor(&mut path_stack, base_path, path_context, relative_path)?;

let paths: Vec<&str> = path_stack.iter().map(|x| *x).collect();
let mut data: &Json = &self.data;
let mut data: &Json = self.data.as_ref();
for p in paths.iter() {
if *p == "this" {
continue;
Expand All @@ -162,12 +164,8 @@ impl Context {
Ok(data)
}

pub fn data(&self) -> &Json {
&self.data
}

pub fn data_mut(&mut self) -> &mut Json {
&mut self.data
pub fn data_clone(&self) -> Json {
self.data.as_ref().clone()
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/directives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ pub use self::inline::INLINE_DIRECTIVE;
/// -> Result<(), RenderError> {
/// // modify json object
/// let mut ctx_ref = rc.context_mut();
/// if let Some(ref mut m) = ctx_ref.data_mut().as_object_mut() {
/// let mut data = ctx_ref.data_clone();
/// if let Some(ref mut m) = data.as_object_mut() {
/// m.insert("hello".to_string(), to_json(&"world".to_owned()));
/// }
/// *ctx_ref = Context::wraps(&data)?;
/// Ok(())
/// }
///
Expand Down Expand Up @@ -120,9 +122,13 @@ mod test {
-> Result<(), RenderError> {
// modify json object
let mut ctx_ref = rc.context_mut();
if let Some(ref mut m) = ctx_ref.data_mut().as_object_mut().as_mut() {
let mut data = ctx_ref.data_clone();

if let Some(ref mut m) = data.as_object_mut().as_mut() {
m.insert("hello".to_string(), context::to_json(&"war".to_owned()));
}

*ctx_ref = Context::wraps(&data)?;
Ok(())
}),
);
Expand Down

0 comments on commit 288ea1c

Please sign in to comment.