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