intuicio_frontend_simpleton/library/
text.rs1use crate::{Array, Boolean, Integer, Reference, Text};
2use intuicio_core::{define_native_struct, registry::Registry};
3use intuicio_derive::intuicio_function;
4use regex::{Captures, Regex};
5
6use super::bytes::Bytes;
7
8thread_local! {
9 static FORMAT_REGEX: Regex = Regex::new(r#"\{(\d+)\}"#).unwrap();
10}
11
12#[intuicio_function(module_name = "text", use_registry)]
13pub fn length(registry: &Registry, text: Reference) -> Reference {
14 Reference::new_integer(text.read::<Text>().unwrap().len() as Integer, registry)
15}
16
17#[intuicio_function(module_name = "text", use_registry)]
18pub fn character(registry: &Registry, text: Reference, index: Reference) -> Reference {
19 let index = *index.read::<Integer>().unwrap() as usize;
20 text.read::<Text>()
21 .unwrap()
22 .chars()
23 .nth(index)
24 .map(|character| Reference::new_text(Text::from(character), registry))
25 .unwrap_or_default()
26}
27
28#[intuicio_function(module_name = "text", use_registry)]
29pub fn find(
30 registry: &Registry,
31 text: Reference,
32 pattern: Reference,
33 reverse: Reference,
34) -> Reference {
35 if *reverse.read::<Boolean>().unwrap() {
36 text.read::<Text>()
37 .unwrap()
38 .rfind(pattern.read::<Text>().unwrap().as_str())
39 .map(|index| Reference::new_integer(index as Integer, registry))
40 .unwrap_or(Reference::new_integer(-1, registry))
41 } else {
42 text.read::<Text>()
43 .unwrap()
44 .find(pattern.read::<Text>().unwrap().as_str())
45 .map(|index| Reference::new_integer(index as Integer, registry))
46 .unwrap_or(Reference::new_integer(-1, registry))
47 }
48}
49
50#[intuicio_function(module_name = "text", use_registry)]
51pub fn slice(
52 registry: &Registry,
53 text: Reference,
54 index: Reference,
55 count: Reference,
56) -> Reference {
57 let index = *index.read::<Integer>().unwrap() as usize;
58 let count = *count.read::<Integer>().unwrap() as usize;
59 Reference::new_text(
60 text.read::<Text>()
61 .unwrap()
62 .chars()
63 .skip(index)
64 .take(count)
65 .collect::<Text>(),
66 registry,
67 )
68}
69
70#[intuicio_function(module_name = "text", use_registry)]
71pub fn join(registry: &Registry, array: Reference, separator: Reference) -> Reference {
72 Reference::new_text(
73 array
74 .read::<Array>()
75 .unwrap()
76 .iter()
77 .map(|item| item.read::<Text>().unwrap().to_owned())
78 .collect::<Vec<_>>()
79 .join(separator.read::<Text>().unwrap().as_str()),
80 registry,
81 )
82}
83
84#[intuicio_function(module_name = "text", use_registry)]
85pub fn combine(registry: &Registry, a: Reference, b: Reference) -> Reference {
86 Reference::new_text(
87 a.read::<Text>().unwrap().to_owned() + b.read::<Text>().unwrap().as_str(),
88 registry,
89 )
90}
91
92#[intuicio_function(module_name = "text", use_registry)]
93pub fn format(registry: &Registry, template: Reference, arguments: Reference) -> Reference {
94 let arguments = &*arguments.read::<Array>().unwrap();
95 let result = FORMAT_REGEX.with(|regex| {
96 regex
97 .replace_all(
98 template.read::<Text>().unwrap().as_str(),
99 |captures: &Captures| {
100 let capture = &captures[1];
101 capture
102 .parse::<usize>()
103 .map(|index| arguments[index].read::<Text>().unwrap().to_owned())
104 .unwrap_or_else(|_| capture.to_owned())
105 },
106 )
107 .as_ref()
108 .to_owned()
109 });
110 Reference::new_text(result, registry)
111}
112
113#[intuicio_function(module_name = "text", use_registry)]
114pub fn split(registry: &Registry, value: Reference, separator: Reference) -> Reference {
115 let result = value
116 .read::<Text>()
117 .unwrap()
118 .split(separator.read::<Text>().unwrap().as_str())
119 .filter(|part| !part.is_empty())
120 .map(|part| Reference::new_text(part.to_owned(), registry))
121 .collect::<Array>();
122 Reference::new_array(result, registry)
123}
124
125#[intuicio_function(module_name = "text", use_registry)]
126pub fn to_bytes(registry: &Registry, value: Reference) -> Reference {
127 let result = value.read::<Text>().unwrap().as_bytes().to_owned();
128 Reference::new(Bytes::new_raw(result), registry)
129}
130
131#[intuicio_function(module_name = "text", use_registry)]
132pub fn from_bytes(registry: &Registry, bytes: Reference) -> Reference {
133 let result = bytes.read::<Bytes>().unwrap();
134 Reference::new_text(
135 String::from_utf8_lossy(result.get_ref()).to_string(),
136 registry,
137 )
138}
139
140#[intuicio_function(module_name = "text", use_registry)]
141pub fn equals(registry: &Registry, a: Reference, b: Reference) -> Reference {
142 if let (Some(a), Some(b)) = (a.read::<Text>(), b.read::<Text>()) {
143 return Reference::new_boolean(*a == *b, registry);
144 }
145 Reference::null()
146}
147
148#[intuicio_function(module_name = "text", use_registry)]
149pub fn not_equals(registry: &Registry, a: Reference, b: Reference) -> Reference {
150 if let (Some(a), Some(b)) = (a.read::<Text>(), b.read::<Text>()) {
151 return Reference::new_boolean(*a != *b, registry);
152 }
153 Reference::null()
154}
155
156pub fn install(registry: &mut Registry) {
157 registry.add_type(define_native_struct! {
158 registry => mod text struct Text (Text) {}
159 });
160 registry.add_function(length::define_function(registry));
161 registry.add_function(character::define_function(registry));
162 registry.add_function(find::define_function(registry));
163 registry.add_function(slice::define_function(registry));
164 registry.add_function(join::define_function(registry));
165 registry.add_function(combine::define_function(registry));
166 registry.add_function(format::define_function(registry));
167 registry.add_function(split::define_function(registry));
168 registry.add_function(to_bytes::define_function(registry));
169 registry.add_function(from_bytes::define_function(registry));
170 registry.add_function(equals::define_function(registry));
171 registry.add_function(not_equals::define_function(registry));
172}