From cffacc4dc4a46b525250772e87fd69a2f1c64dc2 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 11 Jun 2026 11:35:24 -0700 Subject: Split things out, made things easier to use. CrimError now has several constructors for different cases, so it's easier to use, using constructors is normalized now. Value has a load of From implementations now so it's much, much, much easier to use in practice. --- src/lib.rs | 110 +++++++++++++++++++------------------------------------------ 1 file changed, 34 insertions(+), 76 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index 9b838f3..b0bc688 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,9 +7,11 @@ mod lexer; mod parser; mod position; mod error; +mod context; pub use error::{CrimError,CrimResult}; pub use position::*; +pub use context::{Context,Value,MappedStructure}; #[derive(Debug)] pub struct Crimtag { @@ -39,7 +41,7 @@ struct View { } impl View { - fn process(&self, input: &impl MappedStructure) -> Result { + fn process(&self, input: &impl MappedStructure) -> CrimResult { let mut out_vars = Context::new(); for output in &self.outputs { let mut buf = String::new(); @@ -68,16 +70,6 @@ enum Token { Text(String), } -#[derive(Debug,Clone)] -pub enum Value { - Dictionary(Context), - List(Vec), - String(String), - Int(i64), - Float(f64), - Identifier(Identifier), -} - #[derive(Debug,Clone)] pub enum IdentifierValue { Name(String), @@ -85,40 +77,6 @@ pub enum IdentifierValue { } pub type Identifier = Vec; -pub type Context = HashMap; - -pub trait MappedStructure { - fn get_value(&self, id: &Identifier) -> Option; -} - -impl MappedStructure for Context { - fn get_value(&self, id: &Identifier) -> Option { - if id.len() == 0 { - return None; - } - let mut cur_val : Option<&Value> = if let IdentifierValue::Name(s) = &id[0] { - self.get(s) - } else { - return None; - }; - if cur_val.is_none() { - return None; - } - - for idx in 1..id.len() { - if let IdentifierValue::Name(s) = &id[idx] && - let Some(Value::Dictionary(d)) = &cur_val { - cur_val.replace( if let Some(v) = d.get(s) { - v - } else { - return None; - }); - } - } - - return cur_val.cloned(); - } -} impl Crimtag { pub fn new() -> Self { @@ -169,13 +127,13 @@ impl Crimtag { Ok(()) } - pub fn load_static(&mut self, data: &str) -> Result<(),CrimError> { + pub fn load_static(&mut self, data: &str) -> CrimResult<()> { let source_id = self.id_source( &ViewSource::Static ); let p = parser::Parser::new(); self.register_views( p.parse( &data, source_id )? ) } - pub fn load_external(&mut self, key: &str, data: &str) -> Result<(),CrimError> { + pub fn load_external(&mut self, key: &str, data: &str) -> CrimResult<()> { let source_id = self.id_source( &ViewSource::External{ key: key.to_string()} ); @@ -186,7 +144,7 @@ impl Crimtag { ) } - fn register_views(&mut self, views: Vec) -> Result<(),CrimError> { + fn register_views(&mut self, views: Vec) -> CrimResult<()> { for view in views { self.views.insert( view.name.clone(), view ); } @@ -205,15 +163,15 @@ impl Crimtag { } } - pub fn render_partial(&self, view: &str, input: &impl MappedStructure ) -> Result { + pub fn render_partial(&self, view: &str, input: &impl MappedStructure ) -> CrimResult { if let Some(view) = self.views.get(view) { return view.process( input ) } else { - return Err(CrimError::new(Position::none(),"No such view found".into())); + return Err(CrimError::other("No such view found".into())); } } - pub fn render(&self, view: &str, input: &impl MappedStructure ) -> Result { + pub fn render(&self, view: &str, input: &impl MappedStructure ) -> CrimResult { if let Some(view) = self.views.get( view ) { let mut output = view.process( input )?; if let Some(l) = &view.layout { @@ -224,17 +182,17 @@ impl Crimtag { Ok(s) } else { - Err(CrimError::new(Position::none(), "No content found in root layout.".into())) + Err(CrimError::other("No content found in root layout.".into())) } } } else { - Err(CrimError::new(Position::none(),"No such view found".into())) + Err(CrimError::other("No such view found".into())) } } } -fn exec(input: &impl MappedStructure, tokens: &Vec, buf: &mut String) -> Result<(),CrimError> { +fn exec(input: &impl MappedStructure, tokens: &Vec, buf: &mut String) -> CrimResult<()> { for token in tokens { match token { Token::Loop(ident,code) => { @@ -363,28 +321,28 @@ Now with explicit outputs: } let ctx = Context::from([ - ("people".to_string(), crate::Value::List(vec![ - crate::Value::Dictionary(Context::from([ - ("first_name".to_string(), Value::String("Joe".to_string())), - ("last_name".to_string(), Value::String("Smith".to_string())), - ("title".to_string(), Value::String("CEO".to_string())), - ])), - crate::Value::Dictionary(Context::from([ - ("first_name".to_string(), Value::String("Chris".to_string())), - ("last_name".to_string(), Value::String("Perkens".to_string())), - ("title".to_string(), Value::String("Baconeer".to_string())), - ])), - crate::Value::Dictionary(Context::from([ - ("first_name".to_string(), Value::String("Will".to_string())), - ("last_name".to_string(), Value::String("Power".to_string())), - ("title".to_string(), Value::String("CFO".to_string())), - ])), - crate::Value::Dictionary(Context::from([ - ("first_name".to_string(), Value::String("Justin".to_string())), - ("last_name".to_string(), Value::String("Time".to_string())), - ("title".to_string(), Value::String("CIO".to_string())), - ])), - ])), + ("people".to_string(), vec![ + [ + ("first_name".into(), "Joe".into()), + ("last_name".into(), "Smith".into()), + ("title".into(), "CEO".into()), + ].into(), + [ + ("first_name".into(), "Chris".into()), + ("last_name".into(), "Perkens".into()), + ("title".into(), "Baconeer".into()), + ].into(), + [ + ("first_name".into(), "Will".into()), + ("last_name".into(), "Power".into()), + ("title".into(), "CFO".into()), + ].into(), + [ + ("first_name".into(), "Justin".into()), + ("last_name".into(), "Time".into()), + ("title".into(), "CIO".into()), + ].into(), + ].into()), ]); match ct.render("index", &ctx) { Ok(s) => println!("View result: {}", s ), -- cgit v1.2.3