Compare commits

...

2 Commits

Author SHA1 Message Date
PedroEdiaz
c466e55169 Add Integer and Enum Decode 2025-06-17 18:46:30 -06:00
PedroEdiaz
fedfd70c50 Change map -> struct 2025-06-17 11:43:52 -06:00
4 changed files with 102 additions and 22 deletions

View File

@@ -1,5 +1,5 @@
# Templateless # Mustacheless
A lightweight, logicless templating library for the A subset of {{mustache}}, logicless templating library for the
[Odin programming language](https://odin-lang.org/). This library allows you to [Odin programming language](https://odin-lang.org/). This library allows you to
define templates using placeholder variables within strings and replace them define templates using placeholder variables within strings and replace them
with values from a provided dictionary. with values from a provided dictionary.

81
decode.odin Normal file
View File

@@ -0,0 +1,81 @@
package mustache
import "base:runtime"
import "core:reflect"
import "core:strconv"
import "core:log"
decode :: proc( v: any, key: string ) -> string {
if v == nil do return ""
ti := runtime.type_info_base(type_info_of(v.id))
a := any{v.data, ti.id}
#partial switch info in ti.variant {
case runtime.Type_Info_Struct:
return decode( reflect.struct_field_value_by_name(v, key), "." )
case runtime.Type_Info_String:
if key != "." do return ""
switch t in a {
case string:
return t
case cstring:
return string(t)
}
case runtime.Type_Info_Integer:
if key != "." do return ""
buf: [40]byte
u := cast_any_int_to_u128(a)
return strconv.append_bits_128(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil)
case runtime.Type_Info_Enum:
return decode(any{v.data, info.base.id}, key)
}
return ""
}
@(private)
cast_any_int_to_u128 :: proc(any_int_value: any) -> u128 {
u: u128 = 0
switch i in any_int_value {
case i8: u = u128(i)
case i16: u = u128(i)
case i32: u = u128(i)
case i64: u = u128(i)
case i128: u = u128(i)
case int: u = u128(i)
case u8: u = u128(i)
case u16: u = u128(i)
case u32: u = u128(i)
case u64: u = u128(i)
case u128: u = u128(i)
case uint: u = u128(i)
case uintptr: u = u128(i)
case i16le: u = u128(i)
case i32le: u = u128(i)
case i64le: u = u128(i)
case u16le: u = u128(i)
case u32le: u = u128(i)
case u64le: u = u128(i)
case u128le: u = u128(i)
case i16be: u = u128(i)
case i32be: u = u128(i)
case i64be: u = u128(i)
case u16be: u = u128(i)
case u32be: u = u128(i)
case u64be: u = u128(i)
case u128be: u = u128(i)
}
return u;
}

View File

@@ -1,4 +1,4 @@
package template package mustache
import "core:strings" import "core:strings"
@@ -20,7 +20,7 @@ A new string with all placeholders replaced by their corresponding values from
the dictionary. If a key is missing in the dictionary, the placeholder is the dictionary. If a key is missing in the dictionary, the placeholder is
replaces with an empty string. replaces with an empty string.
*/ */
template :: proc(fmt: string, dict: map[string]string ) -> string { mustache :: proc(fmt: string, v: any ) -> string {
/* /*
template works as a state machine, it manipulates `b` (returned string) template works as a state machine, it manipulates `b` (returned string)
and `key` (placeholder string), according to the states. No error and `key` (placeholder string), according to the states. No error
@@ -52,7 +52,7 @@ template :: proc(fmt: string, dict: map[string]string ) -> string {
strings.write_string(&b, "{}" ) strings.write_string(&b, "{}" )
s=.writing s=.writing
case .close_bracket: case .close_bracket:
strings.write_string(&b, dict[strings.to_string(key)] ) strings.write_string(&b, decode(v, strings.to_string(key) ))
strings.builder_reset(&key) strings.builder_reset(&key)
s=.writing s=.writing
case .writing: case .writing:

View File

@@ -1,41 +1,41 @@
#+feature dynamic-literals #+feature dynamic-literals
#+private #+private
package template package mustache
import "core:testing" import "core:testing"
@(test) @(test)
test1 :: proc(t: ^testing.T){ test1 :: proc(t: ^testing.T){
fmt := "{" fmt := "{"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp==fmt, tmp) testing.expect(t, tmp==fmt, tmp)
} }
@(test) @(test)
test2 :: proc(t: ^testing.T){ test2 :: proc(t: ^testing.T){
fmt := "}" fmt := "}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp==fmt, tmp) testing.expect(t, tmp==fmt, tmp)
} }
@(test) @(test)
test3 :: proc(t: ^testing.T){ test3 :: proc(t: ^testing.T){
fmt := "{{" fmt := "{{"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp==fmt, tmp) testing.expect(t, tmp==fmt, tmp)
} }
@(test) @(test)
test4 :: proc(t: ^testing.T){ test4 :: proc(t: ^testing.T){
fmt := "{{}" fmt := "{{}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp==fmt, tmp) testing.expect(t, tmp==fmt, tmp)
} }
@(test) @(test)
test5 :: proc(t: ^testing.T){ test5 :: proc(t: ^testing.T){
fmt := "{{}}" fmt := "{{}}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp=="", tmp) testing.expect(t, tmp=="", tmp)
} }
@@ -43,66 +43,65 @@ test5 :: proc(t: ^testing.T){
test6 :: proc(t: ^testing.T){ test6 :: proc(t: ^testing.T){
fmt := "{{foo}}" fmt := "{{foo}}"
dict := map[string]string{"foo"="var"} dict : struct { foo: string } = {"var"}
defer delete(dict)
tmp := template(fmt, dict) tmp := mustache(fmt, dict)
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp=="var", tmp) testing.expect(t, tmp=="var", tmp)
} }
@(test) @(test)
test7 :: proc(t: ^testing.T){ test7 :: proc(t: ^testing.T){
fmt := "{{{}}" fmt := "{{{}}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp=="", tmp) testing.expect(t, tmp=="", tmp)
} }
@(test) @(test)
test8 :: proc(t: ^testing.T){ test8 :: proc(t: ^testing.T){
fmt := "{{}}}" fmt := "{{}}}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp=="}", tmp) testing.expect(t, tmp=="}", tmp)
} }
@(test) @(test)
test9 :: proc(t: ^testing.T){ test9 :: proc(t: ^testing.T){
fmt := "{{{}}}" fmt := "{{{}}}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp=="}", tmp) testing.expect(t, tmp=="}", tmp)
} }
@(test) @(test)
test10 :: proc(t: ^testing.T){ test10 :: proc(t: ^testing.T){
fmt := "{{} }}" fmt := "{{} }}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp=="", tmp) testing.expect(t, tmp=="", tmp)
} }
@(test) @(test)
test11 :: proc(t: ^testing.T){ test11 :: proc(t: ^testing.T){
fmt := "{{{} }}" fmt := "{{{} }}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp=="", tmp) testing.expect(t, tmp=="", tmp)
} }
@(test) @(test)
test12 :: proc(t: ^testing.T){ test12 :: proc(t: ^testing.T){
fmt := " {{{} }}" fmt := " {{{} }}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp==" ", tmp) testing.expect(t, tmp==" ", tmp)
} }
@(test) @(test)
test13 :: proc(t: ^testing.T){ test13 :: proc(t: ^testing.T){
fmt := "{{{} }} " fmt := "{{{} }} "
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp==" ", tmp) testing.expect(t, tmp==" ", tmp)
} }
@(test) @(test)
test14 :: proc(t: ^testing.T){ test14 :: proc(t: ^testing.T){
fmt := "{{{}}}" fmt := "{{{}}}"
tmp := template(fmt,{}) tmp := mustache(fmt,{})
defer delete(tmp) defer delete(tmp)
testing.expect(t, tmp=="}", tmp) testing.expect(t, tmp=="}", tmp)
} }