Switch the Renderable trait over to the returning a RenderError

This commit is contained in:
Tom Alexander 2020-04-12 21:03:55 -04:00
parent 9c7883358a
commit 610adc8b72
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 36 additions and 22 deletions

View File

@ -73,14 +73,14 @@ fn read_context_from_stdin() -> serde_json::Value {
impl ContextElement for serde_json::Value {} impl ContextElement for serde_json::Value {}
impl Renderable for serde_json::Value { impl Renderable for serde_json::Value {
fn render(&self) -> String { fn render(&self) -> Result<String, RenderError> {
match self { match self {
serde_json::Value::Null => "".to_owned(), serde_json::Value::Null => Ok("".to_owned()),
serde_json::Value::Bool(boolean) => boolean.to_string(), serde_json::Value::Bool(boolean) => Ok(boolean.to_string()),
serde_json::Value::Number(num) => num.to_string(), serde_json::Value::Number(num) => Ok(num.to_string()),
serde_json::Value::String(string) => string.to_string(), serde_json::Value::String(string) => Ok(string.to_string()),
serde_json::Value::Array(_arr) => panic!("Attempted to render an array"), serde_json::Value::Array(_arr) => Err(RenderError::CantRender { elem: self }),
serde_json::Value::Object(_obj) => panic!("Attempted to render an object"), serde_json::Value::Object(_obj) => Err(RenderError::CantRender { elem: self }),
} }
} }
} }
@ -105,7 +105,6 @@ impl Walkable for serde_json::Value {
elem: self, elem: self,
}), }),
serde_json::Value::Array(_arr) => todo!("Arrays not supported yet"), serde_json::Value::Array(_arr) => todo!("Arrays not supported yet"),
// TODO: Handle this error better
serde_json::Value::Object(obj) => { serde_json::Value::Object(obj) => {
obj.get(segment) obj.get(segment)
.map(|val| val as _) .map(|val| val as _)

View File

@ -14,6 +14,10 @@ pub enum RenderError<'a> {
segment: String, segment: String,
elem: &'a dyn ContextElement, elem: &'a dyn ContextElement,
}, },
/// Attempting to render and unrenderable type (for example, an object without any filters)
CantRender {
elem: &'a dyn ContextElement,
},
} }
#[derive(Clone)] #[derive(Clone)]
@ -31,6 +35,7 @@ impl fmt::Display for RenderError<'_> {
RenderError::WontWalk { segment, elem } => { RenderError::WontWalk { segment, elem } => {
write!(f, "Failed to walk to {} from {:?}", segment, elem) write!(f, "Failed to walk to {} from {:?}", segment, elem)
} }
RenderError::CantRender { elem } => write!(f, "Cant render {:?}", elem),
} }
} }
} }
@ -45,6 +50,7 @@ impl fmt::Debug for RenderError<'_> {
RenderError::WontWalk { segment, elem } => { RenderError::WontWalk { segment, elem } => {
write!(f, "Failed to walk to {} from {:?}", segment, elem) write!(f, "Failed to walk to {} from {:?}", segment, elem)
} }
RenderError::CantRender { elem } => write!(f, "Cant render {:?}", elem),
} }
} }
} }

View File

@ -1,3 +1,5 @@
use crate::renderer::errors::RenderError;
pub trait Renderable { pub trait Renderable {
fn render(&self) -> String; fn render(&self) -> Result<String, RenderError>;
} }

View File

@ -85,10 +85,10 @@ impl<'a> DustRenderer<'a> {
C: ContextElement, C: ContextElement,
{ {
match tag { match tag {
DustTag::DTComment(comment) => (), DustTag::DTComment(_comment) => (),
DustTag::DTReference(reference) => { DustTag::DTReference(reference) => {
let val = walk_path(context, &reference.path.keys)?; let val = walk_path(context, &reference.path.keys)?;
return Ok(val.render()); return val.render();
} }
_ => (), // TODO: Implement the rest _ => (), // TODO: Implement the rest
} }
@ -120,20 +120,20 @@ mod tests {
impl<I: ContextElement> ContextElement for HashMap<&str, I> {} impl<I: ContextElement> ContextElement for HashMap<&str, I> {}
impl Renderable for u32 { impl Renderable for u32 {
fn render(&self) -> std::string::String { fn render(&self) -> Result<String, RenderError> {
self.to_string() Ok(self.to_string())
} }
} }
impl Renderable for &str { impl Renderable for &str {
fn render(&self) -> std::string::String { fn render(&self) -> Result<String, RenderError> {
self.to_string() Ok(self.to_string())
} }
} }
impl<I: ContextElement> Renderable for HashMap<&str, I> { impl<I: ContextElement> Renderable for HashMap<&str, I> {
fn render(&self) -> std::string::String { fn render(&self) -> Result<String, RenderError> {
panic!("Attempted to render a hashmap"); Err(RenderError::CantRender { elem: self })
} }
} }
@ -182,16 +182,23 @@ mod tests {
.iter() .iter()
.cloned() .cloned()
.collect(); .collect();
assert_eq!(walk_path(&context, &vec!["cat"]).unwrap().render(), "kitty");
assert_eq!( assert_eq!(
walk_path(&number_context, &vec!["tiger"]).unwrap().render(), walk_path(&context, &vec!["cat"]).unwrap().render().unwrap(),
"3" "kitty".to_owned()
);
assert_eq!(
walk_path(&number_context, &vec!["tiger"])
.unwrap()
.render()
.unwrap(),
"3".to_owned()
); );
assert_eq!( assert_eq!(
walk_path(&deep_context, &vec!["tiger", "food"]) walk_path(&deep_context, &vec!["tiger", "food"])
.unwrap() .unwrap()
.render(), .render()
"people" .unwrap(),
"people".to_owned()
); );
} }
} }