summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2026-06-17 00:05:37 -0700
committerMike Buland <mike@xagasoft.com>2026-06-17 00:05:37 -0700
commit00ffb6d11ed3a1d6508cbf065679b6f04673f238 (patch)
tree6b463d2ceab2ffe96a1d32c1cca91a9da2671b2f /src/lib.rs
parent68745e87a73ed7cfa305ee5319b85aeef85eb088 (diff)
downloadcrimtag-00ffb6d11ed3a1d6508cbf065679b6f04673f238.tar.gz
crimtag-00ffb6d11ed3a1d6508cbf065679b6f04673f238.tar.bz2
crimtag-00ffb6d11ed3a1d6508cbf065679b6f04673f238.tar.xz
crimtag-00ffb6d11ed3a1d6508cbf065679b6f04673f238.zip
I think this is a better structure.
We deal with mapped structures better now, and they are distinct from our handy value tree. I haven't figured out how to make it like iterators yet, but I think we're close...
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs174
1 files changed, 156 insertions, 18 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 362e017..eda2f31 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,7 +11,7 @@ mod context;
11 11
12pub use error::{CrimError,CrimResult}; 12pub use error::{CrimError,CrimResult};
13pub use position::*; 13pub use position::*;
14pub use context::{Context,Value,MappedStructure,StatefulContext}; 14pub use context::{Context,Value,MappedStructure,StatefulContext,MappedValue,MappedList};
15 15
16#[derive(Debug)] 16#[derive(Debug)]
17pub struct Crimtag { 17pub struct Crimtag {
@@ -41,7 +41,7 @@ struct View {
41} 41}
42 42
43impl View { 43impl View {
44 fn process<T: MappedStructure>(&self, input: &T) -> CrimResult<Context> { 44 fn process<T: for<'a> MappedStructure<'a>>(&self, input: &T) -> CrimResult<Context> {
45 let mut out_vars = Context::new(); 45 let mut out_vars = Context::new();
46 for output in &self.outputs { 46 for output in &self.outputs {
47 let mut buf = String::new(); 47 let mut buf = String::new();
@@ -163,7 +163,7 @@ impl Crimtag {
163 } 163 }
164 } 164 }
165 165
166 pub fn render_partial<T: MappedStructure>(&self, view: &str, input: &T ) -> CrimResult<Context> { 166 pub fn render_partial<T: for<'a> MappedStructure<'a>>(&self, view: &str, input: &T ) -> CrimResult<Context> {
167 if let Some(view) = self.views.get(view) { 167 if let Some(view) = self.views.get(view) {
168 return view.process( input ) 168 return view.process( input )
169 } else { 169 } else {
@@ -171,7 +171,7 @@ impl Crimtag {
171 } 171 }
172 } 172 }
173 173
174 pub fn render<T: MappedStructure>(&self, view: &str, input: &T ) -> CrimResult<String> { 174 pub fn render<T: for<'a> MappedStructure<'a>>(&self, view: &str, input: &T ) -> CrimResult<String> {
175 if let Some(view) = self.views.get( view ) { 175 if let Some(view) = self.views.get( view ) {
176 //println!("::Token tree::\n{:?}", view ); 176 //println!("::Token tree::\n{:?}", view );
177 let mut output = view.process( input )?; 177 let mut output = view.process( input )?;
@@ -193,10 +193,11 @@ impl Crimtag {
193 } 193 }
194} 194}
195 195
196fn exec<T: MappedStructure>(input: &StatefulContext<T>, tokens: &Vec<Token>, buf: &mut String) -> CrimResult<()> { 196fn exec<T: for<'a> MappedStructure<'a>>(input: &StatefulContext<T>, tokens: &Vec<Token>, buf: &mut String) -> CrimResult<()> {
197 for token in tokens { 197 for token in tokens {
198 match token { 198 match token {
199 Token::Loop(ident,code) => { 199 Token::Loop(_ident,_code) => {
200 /*
200 if let Some(value) = input.get_value( &ident ) && 201 if let Some(value) = input.get_value( &ident ) &&
201 let Value::List(list) = value { 202 let Value::List(list) = value {
202 for rec in &list { 203 for rec in &list {
@@ -212,10 +213,12 @@ fn exec<T: MappedStructure>(input: &StatefulContext<T>, tokens: &Vec<Token>, buf
212 } 213 }
213 } 214 }
214 } 215 }
216 */
217 return Ok(());
215 } 218 }
216 Token::If(ident,code,other) => { 219 Token::If(ident,code,other) => {
217 if let Some(value) = input.get_value( &ident ) && 220 if let Some(value) = input.get_value( &ident ) &&
218 let Value::Bool(b) = value && 221 let MappedValue::Bool(b) = value &&
219 b { 222 b {
220 223
221 exec(input, code, buf)? 224 exec(input, code, buf)?
@@ -231,34 +234,62 @@ fn exec<T: MappedStructure>(input: &StatefulContext<T>, tokens: &Vec<Token>, buf
231 }; 234 };
232 if let Some(value) = input.get_value( &ident ) { 235 if let Some(value) = input.get_value( &ident ) {
233 match value { 236 match value {
234 Value::Dictionary(_) => { 237 MappedValue::Struct(_) => {
235 buf.push_str("<dictionary>"); 238 buf.push_str("Struct");
236 } 239 }
237 Value::List(_) => { 240 MappedValue::List(_) => {
238 buf.push_str("<list>"); 241 buf.push_str("List");
239 } 242 }
240 Value::Bool(b) => { 243 MappedValue::Bool(b) => {
241 if b { 244 if b {
242 buf.push_str("true"); 245 buf.push_str("true");
243 } else { 246 } else {
244 buf.push_str("false"); 247 buf.push_str("false");
245 } 248 }
246 } 249 }
247 Value::String(s) => { 250 MappedValue::Str(s) => {
251 buf.push_str(s);
252 }
253 MappedValue::String(s) => {
248 buf.push_str(s.as_str()); 254 buf.push_str(s.as_str());
249 } 255 }
250 Value::Int(i) => { 256 MappedValue::Int8(i) => {
257 buf.push_str(&i.to_string());
258 }
259 MappedValue::Int16(i) => {
260 buf.push_str(&i.to_string());
261 }
262 MappedValue::Int32(i) => {
263 buf.push_str(&i.to_string());
264 }
265 MappedValue::Int64(i) => {
266 buf.push_str(&i.to_string());
267 }
268 MappedValue::UInt8(i) => {
269 buf.push_str(&i.to_string());
270 }
271 MappedValue::UInt16(i) => {
272 buf.push_str(&i.to_string());
273 }
274 MappedValue::UInt32(i) => {
251 buf.push_str(&i.to_string()); 275 buf.push_str(&i.to_string());
252 } 276 }
253 Value::Float(f) => { 277 MappedValue::UInt64(i) => {
278 buf.push_str(&i.to_string());
279 }
280 MappedValue::Float32(f) => {
254 if format == "" { 281 if format == "" {
255 buf.push_str(&f.to_string()); 282 buf.push_str(&f.to_string());
256 } else { 283 } else {
257 buf.push_str(&f.to_string()); 284 buf.push_str(&f.to_string());
258 } 285 }
259 } 286 }
260 Value::Identifier(_) => { 287 MappedValue::Float64(f) => {
261 // ??? 288 if format == "" {
289 buf.push_str(&f.to_string());
290 } else {
291 buf.push_str(&f.to_string());
292 }
262 } 293 }
263 } 294 }
264 } 295 }
@@ -266,7 +297,7 @@ fn exec<T: MappedStructure>(input: &StatefulContext<T>, tokens: &Vec<Token>, buf
266 Token::Text(s) => { 297 Token::Text(s) => {
267 buf.push_str( s ); 298 buf.push_str( s );
268 } 299 }
269 _ => {} 300 //_ => {}
270 } 301 }
271 } 302 }
272 Ok(()) 303 Ok(())
@@ -394,4 +425,111 @@ Now with explicit outputs:
394 425
395 Ok(()) 426 Ok(())
396 } 427 }
428
429 struct Item {
430 pub id: i32,
431 pub title: String,
432 pub body: String,
433 }
434
435 struct Person {
436 pub id: i32,
437 pub username: String,
438 pub name: String,
439 }
440
441 struct Page {
442 pub user: Person,
443 pub total_items: i32,
444 pub total_pages: i32,
445 pub cur_page: i32,
446 pub items: Vec<Item>,
447 }
448
449 impl Page {
450 fn new() -> Page {
451 Page {
452 user: Person {
453 id: 443,
454 username: "eichlan".into(),
455 name: "Mike".into(),
456 },
457 total_items: 4000,
458 total_pages: 400,
459 cur_page: 35,
460 items: vec![
461 Item{
462 id: 123,
463 title: "hi".into(),
464 body: "body".into(),
465 },
466 Item{
467 id: 124,
468 title: "bye".into(),
469 body: "wooo".into(),
470 },
471 Item{
472 id: 125,
473 title: "ciao".into(),
474 body: "whatever".into(),
475 }
476 ],
477 }
478 }
479 }
480
481 impl<'a> MappedStructure<'a> for Page {
482 fn get_value(&'a self, id: &str) -> Option<MappedValue<'a>> {
483 match id {
484 "user" => Some(MappedValue::Struct(&self.user)),
485 "total_items" => Some(MappedValue::Int32(self.total_items)),
486 "total_pages" => Some(MappedValue::Int32(self.total_pages)),
487 "cur_page" => Some(MappedValue::Int32(self.cur_page)),
488 "items" => Some(MappedValue::<'a>::List(&self.items)),
489 _ => None,
490 }
491 }
492 }
493
494 impl<'a> MappedStructure<'a> for Person {
495 fn get_value(&'a self, id: &str) -> Option<MappedValue<'a>> {
496 match id {
497 "id" => Some(MappedValue::Int32(self.id)),
498 "username" => Some(MappedValue::String(&self.username)),
499 "name" => Some(MappedValue::String(&self.name)),
500 _ => None,
501 }
502 }
503 }
504
505 impl<'a> MappedStructure<'a> for Item {
506 fn get_value(&'a self, id: &str) -> Option<MappedValue<'a>> {
507 match id {
508 "id" => Some(MappedValue::Int32(self.id)),
509 "title" => Some(MappedValue::String(&self.title)),
510 "body" => Some(MappedValue::String(&self.body)),
511 _ => None,
512 }
513 }
514 }
515
516 impl<'a> MappedList<'a> for Vec<Item> {
517 fn get_index(&'a self, id: usize) -> Option<MappedValue<'a>> {
518 if let Some(x) = self.get(id) {
519 Some(MappedValue::<'a>::Struct(x))
520 } else {
521 None
522 }
523 }
524 }
525
526 #[test]
527 fn custom() -> Result<(), CrimError> {
528 let page = Page::new();
529
530 println!("{:?}",
531 page.get_value(&"total_pages")
532 );
533 Ok(())
534 }
397} 535}