shape_jit/ffi/object/
format.rs1use super::super::super::context::JITContext;
12use super::super::super::nan_boxing::*;
13
14#[inline(always)]
20pub extern "C" fn jit_format(ctx: *mut JITContext, _arg_count: usize) -> u64 {
21 unsafe {
22 if ctx.is_null() {
23 return TAG_NULL;
24 }
25
26 let ctx_ref = &mut *ctx;
27
28 if ctx_ref.stack_ptr == 0 {
30 return TAG_NULL;
31 }
32 ctx_ref.stack_ptr -= 1;
33 let arg_count_val = ctx_ref.stack[ctx_ref.stack_ptr];
34 let arg_count = if is_number(arg_count_val) {
35 unbox_number(arg_count_val) as usize
36 } else {
37 return TAG_NULL;
38 };
39
40 if arg_count == 0 {
41 return TAG_NULL;
42 }
43
44 let mut args = Vec::with_capacity(arg_count);
46 for _ in 0..arg_count {
47 if ctx_ref.stack_ptr == 0 {
48 return TAG_NULL;
49 }
50 ctx_ref.stack_ptr -= 1;
51 args.push(ctx_ref.stack[ctx_ref.stack_ptr]);
52 }
53 args.reverse(); let template_bits = args[0];
57 if !is_heap_kind(template_bits, HK_STRING) {
58 return TAG_NULL;
59 }
60 let template = jit_unbox::<String>(template_bits).clone();
61
62 let mut result = template;
64 let format_args = &args[1..];
65
66 let mut arg_idx = 0;
68 while let Some(pos) = result.find("{}") {
69 if arg_idx < format_args.len() {
70 let replacement = value_to_string(format_args[arg_idx]);
71 result = format!("{}{}{}", &result[..pos], replacement, &result[pos + 2..]);
72 arg_idx += 1;
73 } else {
74 break;
75 }
76 }
77
78 for i in 0..format_args.len() {
80 let placeholder = format!("{{{}}}", i);
81 if result.contains(&placeholder) {
82 let replacement = value_to_string(format_args[i]);
83 result = result.replace(&placeholder, &replacement);
84 }
85 }
86
87 jit_box(HK_STRING, result)
88 }
89}
90
91pub(crate) fn value_to_string(bits: u64) -> String {
93 if is_number(bits) {
94 let n = unbox_number(bits);
95 if n.fract() == 0.0 && n.abs() < 1e15 {
96 format!("{}", n as i64)
97 } else {
98 format!("{}", n)
99 }
100 } else if bits == TAG_NULL {
101 "null".to_string()
102 } else if bits == TAG_BOOL_TRUE {
103 "true".to_string()
104 } else if bits == TAG_BOOL_FALSE {
105 "false".to_string()
106 } else {
107 match heap_kind(bits) {
108 Some(HK_STRING) => {
109 let s = unsafe { jit_unbox::<String>(bits) };
110 s.clone()
111 }
112 Some(HK_ARRAY) => "[array]".to_string(),
113 Some(HK_JIT_OBJECT) | Some(HK_TYPED_OBJECT) => "[object]".to_string(),
114 _ => "[unknown]".to_string(),
115 }
116 }
117}