#![allow(non_snake_case)] use crate::plugin::*; use crate::stdlib::{format, string::ToString}; use crate::{def_package, FnPtr, ImmutableString}; #[cfg(not(feature = "no_index"))] use crate::Array; #[cfg(not(feature = "no_object"))] use crate::Map; const FUNC_TO_DEBUG: &'static str = "to_debug"; def_package!(crate:BasicStringPackage:"Basic string utilities, including printing.", lib, { combine_with_exported_module!(lib, "print_debug", print_debug_functions); }); // Register print and debug #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] #[inline(always)] fn print_with_func(fn_name: &str, ctx: &NativeCallContext, value: &mut Dynamic) -> ImmutableString { match ctx.call_fn_dynamic_raw(fn_name, true, &mut [value]) { Ok(result) if result.is::() => result.take_immutable_string().unwrap(), Ok(result) => ctx.engine().map_type_name(result.type_name()).into(), Err(_) => ctx.engine().map_type_name(value.type_name()).into(), } } #[export_module] mod print_debug_functions { use crate::ImmutableString; #[rhai_fn(name = "print", name = "to_string", pure)] pub fn print_generic(item: &mut Dynamic) -> ImmutableString { item.to_string().into() } #[rhai_fn(name = "debug", name = "to_debug", pure)] pub fn debug_generic(item: &mut Dynamic) -> ImmutableString { format!("{:?}", item).into() } #[rhai_fn(name = "print", name = "debug")] pub fn print_empty_string() -> ImmutableString { "".to_string().into() } #[rhai_fn(name = "print", name = "to_string")] pub fn print_string(s: ImmutableString) -> ImmutableString { s } #[rhai_fn(name = "debug", name = "to_debug", pure)] pub fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString { f.to_string().into() } #[cfg(not(feature = "no_float"))] pub mod float_functions { #[rhai_fn(name = "print", name = "to_string")] pub fn print_f64(number: f64) -> ImmutableString { let abs = number.abs(); if abs > 10000000000000.0 || abs < 0.0000000000001 { format!("{:e}", number).into() } else { number.to_string().into() } } #[rhai_fn(name = "print", name = "to_string")] pub fn print_f32(number: f32) -> ImmutableString { let abs = number.abs(); if abs > 10000000000000.0 || abs < 0.0000000000001 { format!("{:e}", number).into() } else { number.to_string().into() } } #[rhai_fn(name = "debug", name = "to_debug")] pub fn debug_f64(number: f64) -> ImmutableString { number.to_string().into() } #[rhai_fn(name = "debug", name = "to_debug")] pub fn debug_f32(number: f32) -> ImmutableString { number.to_string().into() } } #[cfg(not(feature = "no_index"))] pub mod array_functions { use super::*; #[rhai_fn( name = "print", name = "to_string", name = "debug", name = "to_debug", pure )] pub fn format_array(ctx: NativeCallContext, array: &mut Array) -> ImmutableString { let len = array.len(); let mut result = crate::stdlib::string::String::with_capacity(len * 5 + 2); result.push_str("["); array.iter_mut().enumerate().for_each(|(i, x)| { result.push_str(&print_with_func(FUNC_TO_DEBUG, &ctx, x)); if i < len - 1 { result.push_str(", "); } }); result.push_str("]"); result.into() } } #[cfg(not(feature = "no_object"))] pub mod map_functions { use super::*; #[rhai_fn( name = "print", name = "to_string", name = "debug", name = "to_debug", pure )] pub fn format_map(ctx: NativeCallContext, map: &mut Map) -> ImmutableString { let len = map.len(); let mut result = crate::stdlib::string::String::with_capacity(len * 5 + 3); result.push_str("#{"); map.iter_mut().enumerate().for_each(|(i, (k, v))| { result.push_str(&format!( "{:?}: {}{}", k, &print_with_func(FUNC_TO_DEBUG, &ctx, v), if i < len - 1 { ", " } else { "" } )); }); result.push_str("}"); result.into() } } }