1use super::iter_basic::CharsStream;
2use crate::plugin::*;
3use crate::{def_package, FnPtr, ImmutableString, SmartString, INT};
4use std::any::TypeId;
5use std::fmt::{Binary, LowerHex, Octal, Write};
6#[cfg(feature = "no_std")]
7use std::prelude::v1::*;
8
9#[cfg(not(feature = "no_index"))]
10use crate::Array;
11
12#[cfg(not(feature = "no_object"))]
13use crate::Map;
14
15pub const FUNC_TO_STRING: &str = "to_string";
19
20pub const FUNC_TO_DEBUG: &str = "to_debug";
24
25def_package! {
26 pub BasicStringPackage(lib) {
28 lib.set_standard_lib(true);
29
30 combine_with_exported_module!(lib, "print_debug", print_debug_functions);
31 combine_with_exported_module!(lib, "number_formatting", number_formatting);
32 combine_with_exported_module!(lib, "char", char_functions);
33
34 lib.set_iterator::<CharsStream>();
36
37 lib.set_iter(TypeId::of::<ImmutableString>(), |value| Box::new(
38 CharsStream::new(value.cast::<ImmutableString>().as_str(), 0, INT::MAX).map(Into::into)
39 ));
40 }
41}
42
43#[inline]
45pub fn print_with_func(
46 fn_name: &str,
47 ctx: &NativeCallContext,
48 value: &mut Dynamic,
49) -> ImmutableString {
50 match ctx.call_native_fn_raw(fn_name, true, &mut [value]) {
51 Ok(result) if result.is_string() => result.into_immutable_string().unwrap(),
52 Ok(result) => ctx.engine().map_type_name(result.type_name()).into(),
53 Err(_) => {
54 let mut buf = SmartString::new_const();
55 match fn_name {
56 FUNC_TO_DEBUG => write!(&mut buf, "{value:?}").unwrap(),
57 _ => write!(&mut buf, "{value}").unwrap(),
58 }
59 ctx.engine().map_type_name(&buf).into()
60 }
61 }
62}
63
64#[export_module]
65mod print_debug_functions {
66 #[rhai_fn(name = "print", pure)]
68 pub fn print_generic(ctx: NativeCallContext, item: &mut Dynamic) -> ImmutableString {
69 print_with_func(FUNC_TO_STRING, &ctx, item)
70 }
71 #[rhai_fn(name = "to_string", pure)]
73 pub fn to_string_generic(ctx: NativeCallContext, item: &mut Dynamic) -> ImmutableString {
74 let mut buf = SmartString::new_const();
75 write!(&mut buf, "{item}").unwrap();
76 ctx.engine().map_type_name(&buf).into()
77 }
78 #[rhai_fn(name = "debug", pure)]
80 pub fn debug_generic(ctx: NativeCallContext, item: &mut Dynamic) -> ImmutableString {
81 print_with_func(FUNC_TO_DEBUG, &ctx, item)
82 }
83 #[rhai_fn(name = "to_debug", pure)]
85 pub fn to_debug_generic(ctx: NativeCallContext, item: &mut Dynamic) -> ImmutableString {
86 let mut buf = SmartString::new_const();
87 write!(&mut buf, "{item:?}").unwrap();
88 ctx.engine().map_type_name(&buf).into()
89 }
90
91 #[rhai_fn(name = "print", name = "debug")]
93 pub fn print_empty_string(ctx: NativeCallContext) -> ImmutableString {
94 ctx.engine().const_empty_string()
95 }
96
97 #[rhai_fn(name = "print", name = "to_string")]
99 pub const fn print_string(string: ImmutableString) -> ImmutableString {
100 string
101 }
102 #[rhai_fn(name = "debug", name = "to_debug")]
104 pub fn debug_string(string: &str) -> ImmutableString {
105 let mut buf = SmartString::new_const();
106 write!(&mut buf, "{string:?}").unwrap();
107 buf.into()
108 }
109
110 #[rhai_fn(name = "print", name = "to_string")]
112 pub fn print_char(character: char) -> ImmutableString {
113 let mut buf = SmartString::new_const();
114 buf.push(character);
115 buf.into()
116 }
117 #[rhai_fn(name = "debug", name = "to_debug")]
119 pub fn debug_char(character: char) -> ImmutableString {
120 let mut buf = SmartString::new_const();
121 buf.push(character);
122 buf.into()
123 }
124
125 #[rhai_fn(name = "debug", name = "to_debug", pure)]
127 pub fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString {
128 let mut buf = SmartString::new_const();
129 write!(&mut buf, "{f}").unwrap();
130 buf.into()
131 }
132
133 #[rhai_fn(name = "print", name = "to_string")]
135 pub fn print_bool(value: bool) -> ImmutableString {
136 let mut buf = SmartString::new_const();
137 write!(&mut buf, "{value}").unwrap();
138 buf.into()
139 }
140 #[rhai_fn(name = "debug", name = "to_debug")]
142 pub fn debug_bool(value: bool) -> ImmutableString {
143 let mut buf = SmartString::new_const();
144 write!(&mut buf, "{value:?}").unwrap();
145 buf.into()
146 }
147
148 #[allow(unused_variables)]
150 #[rhai_fn(name = "print", name = "to_string")]
151 pub fn print_unit(ctx: NativeCallContext, unit: ()) -> ImmutableString {
152 ctx.engine().const_empty_string()
153 }
154 #[allow(unused_variables)]
156 #[rhai_fn(name = "debug", name = "to_debug")]
157 pub fn debug_unit(unit: ()) -> ImmutableString {
158 "()".into()
159 }
160
161 #[cfg(not(feature = "no_float"))]
163 #[rhai_fn(name = "print", name = "to_string")]
164 pub fn print_f64(number: f64) -> ImmutableString {
165 let mut buf = SmartString::new_const();
166 write!(&mut buf, "{}", crate::types::FloatWrapper::new(number)).unwrap();
167 buf.into()
168 }
169 #[cfg(not(feature = "no_float"))]
171 #[rhai_fn(name = "print", name = "to_string")]
172 pub fn print_f32(number: f32) -> ImmutableString {
173 let mut buf = SmartString::new_const();
174 write!(&mut buf, "{}", crate::types::FloatWrapper::new(number)).unwrap();
175 buf.into()
176 }
177 #[cfg(not(feature = "no_float"))]
179 #[rhai_fn(name = "debug", name = "to_debug")]
180 pub fn debug_f64(number: f64) -> ImmutableString {
181 let mut buf = SmartString::new_const();
182 write!(&mut buf, "{:?}", crate::types::FloatWrapper::new(number)).unwrap();
183 buf.into()
184 }
185 #[cfg(not(feature = "no_float"))]
187 #[rhai_fn(name = "debug", name = "to_debug")]
188 pub fn debug_f32(number: f32) -> ImmutableString {
189 let mut buf = SmartString::new_const();
190 write!(&mut buf, "{:?}", crate::types::FloatWrapper::new(number)).unwrap();
191 buf.into()
192 }
193
194 #[cfg(not(feature = "no_index"))]
196 #[rhai_fn(
197 name = "print",
198 name = "to_string",
199 name = "debug",
200 name = "to_debug",
201 pure
202 )]
203 pub fn format_array(ctx: NativeCallContext, array: &mut Array) -> ImmutableString {
204 let len = array.len();
205 let mut result = SmartString::new_const();
206 result.push_str("[");
207
208 array.iter_mut().enumerate().for_each(|(i, x)| {
209 result.push_str(&print_with_func(FUNC_TO_DEBUG, &ctx, x));
210 if i < len - 1 {
211 result.push_str(", ");
212 }
213 });
214
215 result.push_str("]");
216 result.into()
217 }
218
219 #[cfg(not(feature = "no_object"))]
221 #[rhai_fn(
222 name = "print",
223 name = "to_string",
224 name = "debug",
225 name = "to_debug",
226 pure
227 )]
228 pub fn format_map(ctx: NativeCallContext, map: &mut Map) -> ImmutableString {
229 let len = map.len();
230 let mut result = SmartString::new_const();
231 result.push_str("#{");
232
233 map.iter_mut().enumerate().for_each(|(i, (k, v))| {
234 write!(
235 result,
236 "{:?}: {}{}",
237 k,
238 &print_with_func(FUNC_TO_DEBUG, &ctx, v),
239 if i < len - 1 { ", " } else { "" }
240 )
241 .unwrap();
242 });
243
244 result.push_str("}");
245 result.into()
246 }
247}
248
249#[export_module]
250mod number_formatting {
251 fn to_hex<T: LowerHex>(value: T) -> ImmutableString {
252 let mut buf = SmartString::new_const();
253 write!(&mut buf, "{value:x}").unwrap();
254 buf.into()
255 }
256 fn to_octal<T: Octal>(value: T) -> ImmutableString {
257 let mut buf = SmartString::new_const();
258 write!(&mut buf, "{value:o}").unwrap();
259 buf.into()
260 }
261 fn to_binary<T: Binary>(value: T) -> ImmutableString {
262 let mut buf = SmartString::new_const();
263 write!(&mut buf, "{value:b}").unwrap();
264 buf.into()
265 }
266
267 #[rhai_fn(name = "to_hex")]
269 pub fn int_to_hex(value: INT) -> ImmutableString {
270 to_hex(value)
271 }
272 #[rhai_fn(name = "to_octal")]
274 pub fn int_to_octal(value: INT) -> ImmutableString {
275 to_octal(value)
276 }
277 #[rhai_fn(name = "to_binary")]
279 pub fn int_to_binary(value: INT) -> ImmutableString {
280 to_binary(value)
281 }
282
283 #[cfg(not(feature = "only_i32"))]
284 #[cfg(not(feature = "only_i64"))]
285 pub mod numbers {
286 #[rhai_fn(name = "to_hex")]
288 pub fn u8_to_hex(value: u8) -> ImmutableString {
289 to_hex(value)
290 }
291 #[rhai_fn(name = "to_hex")]
293 pub fn u16_to_hex(value: u16) -> ImmutableString {
294 to_hex(value)
295 }
296 #[rhai_fn(name = "to_hex")]
298 pub fn u32_to_hex(value: u32) -> ImmutableString {
299 to_hex(value)
300 }
301 #[rhai_fn(name = "to_hex")]
303 pub fn u64_to_hex(value: u64) -> ImmutableString {
304 to_hex(value)
305 }
306 #[rhai_fn(name = "to_hex")]
308 pub fn i8_to_hex(value: i8) -> ImmutableString {
309 to_hex(value)
310 }
311 #[rhai_fn(name = "to_hex")]
313 pub fn i16_to_hex(value: i16) -> ImmutableString {
314 to_hex(value)
315 }
316 #[rhai_fn(name = "to_hex")]
318 pub fn i32_to_hex(value: i32) -> ImmutableString {
319 to_hex(value)
320 }
321 #[rhai_fn(name = "to_hex")]
323 pub fn i64_to_hex(value: i64) -> ImmutableString {
324 to_hex(value)
325 }
326 #[rhai_fn(name = "to_octal")]
328 pub fn u8_to_octal(value: u8) -> ImmutableString {
329 to_octal(value)
330 }
331 #[rhai_fn(name = "to_octal")]
333 pub fn u16_to_octal(value: u16) -> ImmutableString {
334 to_octal(value)
335 }
336 #[rhai_fn(name = "to_octal")]
338 pub fn u32_to_octal(value: u32) -> ImmutableString {
339 to_octal(value)
340 }
341 #[rhai_fn(name = "to_octal")]
343 pub fn u64_to_octal(value: u64) -> ImmutableString {
344 to_octal(value)
345 }
346 #[rhai_fn(name = "to_octal")]
348 pub fn i8_to_octal(value: i8) -> ImmutableString {
349 to_octal(value)
350 }
351 #[rhai_fn(name = "to_octal")]
353 pub fn i16_to_octal(value: i16) -> ImmutableString {
354 to_octal(value)
355 }
356 #[rhai_fn(name = "to_octal")]
358 pub fn i32_to_octal(value: i32) -> ImmutableString {
359 to_octal(value)
360 }
361 #[rhai_fn(name = "to_octal")]
363 pub fn i64_to_octal(value: i64) -> ImmutableString {
364 to_octal(value)
365 }
366 #[rhai_fn(name = "to_binary")]
368 pub fn u8_to_binary(value: u8) -> ImmutableString {
369 to_binary(value)
370 }
371 #[rhai_fn(name = "to_binary")]
373 pub fn u16_to_binary(value: u16) -> ImmutableString {
374 to_binary(value)
375 }
376 #[rhai_fn(name = "to_binary")]
378 pub fn u32_to_binary(value: u32) -> ImmutableString {
379 to_binary(value)
380 }
381 #[rhai_fn(name = "to_binary")]
383 pub fn u64_to_binary(value: u64) -> ImmutableString {
384 to_binary(value)
385 }
386 #[rhai_fn(name = "to_binary")]
388 pub fn i8_to_binary(value: i8) -> ImmutableString {
389 to_binary(value)
390 }
391 #[rhai_fn(name = "to_binary")]
393 pub fn i16_to_binary(value: i16) -> ImmutableString {
394 to_binary(value)
395 }
396 #[rhai_fn(name = "to_binary")]
398 pub fn i32_to_binary(value: i32) -> ImmutableString {
399 to_binary(value)
400 }
401 #[rhai_fn(name = "to_binary")]
403 pub fn i64_to_binary(value: i64) -> ImmutableString {
404 to_binary(value)
405 }
406
407 #[cfg(not(target_family = "wasm"))]
408 pub mod num_128 {
409 #[rhai_fn(name = "to_hex")]
411 pub fn u128_to_hex(value: u128) -> ImmutableString {
412 to_hex(value)
413 }
414 #[rhai_fn(name = "to_hex")]
416 pub fn i128_to_hex(value: i128) -> ImmutableString {
417 to_hex(value)
418 }
419 #[rhai_fn(name = "to_octal")]
421 pub fn u128_to_octal(value: u128) -> ImmutableString {
422 to_octal(value)
423 }
424 #[rhai_fn(name = "to_octal")]
426 pub fn i128_to_octal(value: i128) -> ImmutableString {
427 to_octal(value)
428 }
429 #[rhai_fn(name = "to_binary")]
431 pub fn u128_to_binary(value: u128) -> ImmutableString {
432 to_binary(value)
433 }
434 #[rhai_fn(name = "to_binary")]
436 pub fn i128_to_binary(value: i128) -> ImmutableString {
437 to_binary(value)
438 }
439 }
440 }
441}
442
443#[export_module]
444mod char_functions {
445 pub const fn to_int(ch: char) -> INT {
447 (ch as u32) as INT
448 }
449}