shape_jit/ffi/call_method/
string.rs1use crate::jit_array::JitArray;
12use crate::nan_boxing::*;
13
14#[inline(always)]
16pub fn call_string_method(receiver_bits: u64, method_name: &str, args: &[u64]) -> u64 {
17 unsafe {
18 let s = jit_unbox::<String>(receiver_bits);
19
20 match method_name {
21 "length" | "len" => box_number(s.len() as f64),
22 "toUpperCase" | "to_upper_case" => jit_box(HK_STRING, s.to_uppercase()),
23 "toLowerCase" | "to_lower_case" => jit_box(HK_STRING, s.to_lowercase()),
24 "trim" => jit_box(HK_STRING, s.trim().to_string()),
25 "split" => {
26 let separator = if !args.is_empty() {
27 if is_heap_kind(args[0], HK_STRING) {
28 jit_unbox::<String>(args[0]).clone()
29 } else {
30 " ".to_string()
31 }
32 } else {
33 " ".to_string()
34 };
35
36 let parts: Vec<u64> = s
41 .split(&separator)
42 .map(|part| jit_box(HK_STRING, part.to_string()))
43 .collect();
44
45 jit_box(HK_ARRAY, JitArray::from_vec(parts))
46 }
47 "includes" | "contains" => {
48 if args.is_empty() {
49 return TAG_BOOL_FALSE;
50 }
51 if is_heap_kind(args[0], HK_STRING) {
52 let needle = jit_unbox::<String>(args[0]);
53 if s.contains(needle.as_str()) {
54 return TAG_BOOL_TRUE;
55 }
56 }
57 TAG_BOOL_FALSE
58 }
59 "startsWith" | "starts_with" => {
60 if args.is_empty() {
61 return TAG_BOOL_FALSE;
62 }
63 if is_heap_kind(args[0], HK_STRING) {
64 let prefix = jit_unbox::<String>(args[0]);
65 if s.starts_with(prefix.as_str()) {
66 return TAG_BOOL_TRUE;
67 }
68 }
69 TAG_BOOL_FALSE
70 }
71 "endsWith" | "ends_with" => {
72 if args.is_empty() {
73 return TAG_BOOL_FALSE;
74 }
75 if is_heap_kind(args[0], HK_STRING) {
76 let suffix = jit_unbox::<String>(args[0]);
77 if s.ends_with(suffix.as_str()) {
78 return TAG_BOOL_TRUE;
79 }
80 }
81 TAG_BOOL_FALSE
82 }
83 "replace" | "replaceAll" | "replace_all" => {
84 if args.len() < 2 {
85 return receiver_bits;
86 }
87 if is_heap_kind(args[0], HK_STRING) && is_heap_kind(args[1], HK_STRING) {
88 let from = jit_unbox::<String>(args[0]);
89 let to = jit_unbox::<String>(args[1]);
90 let replaced = s.replace(from.as_str(), to.as_str());
91 return jit_box(HK_STRING, replaced);
92 }
93 receiver_bits
94 }
95 "charAt" | "char_at" => {
96 if args.is_empty() {
97 return jit_box(HK_STRING, String::new());
98 }
99 if is_number(args[0]) {
100 let idx = unbox_number(args[0]) as usize;
101 if let Some(ch) = s.chars().nth(idx) {
102 return jit_box(HK_STRING, ch.to_string());
103 }
104 }
105 jit_box(HK_STRING, String::new())
106 }
107 "substring" | "slice" => {
108 if args.is_empty() {
109 return receiver_bits;
110 }
111 let start = if is_number(args[0]) {
112 unbox_number(args[0]) as usize
113 } else {
114 0
115 };
116 let end = if args.len() > 1 && is_number(args[1]) {
117 unbox_number(args[1]) as usize
118 } else {
119 s.len()
120 };
121 let len = if end >= start { end - start + 1 } else { 0 };
122 let sub: String = s.chars().skip(start).take(len).collect();
123 jit_box(HK_STRING, sub)
124 }
125 "concat" => {
126 let mut result = s.clone();
127 for arg in args.iter() {
128 if is_heap_kind(*arg, HK_STRING) {
129 let arg_s = jit_unbox::<String>(*arg);
130 result.push_str(arg_s);
131 } else if is_number(*arg) {
132 result.push_str(&format!("{}", unbox_number(*arg)));
133 }
134 }
135 jit_box(HK_STRING, result)
136 }
137 "indexOf" | "index_of" => {
138 if args.is_empty() {
139 return box_number(-1.0);
140 }
141 if is_heap_kind(args[0], HK_STRING) {
142 let needle = jit_unbox::<String>(args[0]);
143 if let Some(idx) = s.find(needle.as_str()) {
144 return box_number(idx as f64);
145 }
146 }
147 box_number(-1.0)
148 }
149 "lastIndexOf" | "last_index_of" => {
150 if args.is_empty() {
151 return box_number(-1.0);
152 }
153 if is_heap_kind(args[0], HK_STRING) {
154 let needle = jit_unbox::<String>(args[0]);
155 if let Some(idx) = s.rfind(needle.as_str()) {
156 return box_number(idx as f64);
157 }
158 }
159 box_number(-1.0)
160 }
161 "trimStart" | "trim_start" => jit_box(HK_STRING, s.trim_start().to_string()),
162 "trimEnd" | "trim_end" => jit_box(HK_STRING, s.trim_end().to_string()),
163 "toNumber" | "to_number" => match s.trim().parse::<f64>() {
164 Ok(n) => box_number(n),
165 Err(_) => TAG_NULL,
166 },
167 "toBool" | "to_bool" => match s.trim() {
168 "true" => TAG_BOOL_TRUE,
169 "false" => TAG_BOOL_FALSE,
170 _ => TAG_NULL,
171 },
172 "chars" => {
173 let chars: Vec<u64> = s
178 .chars()
179 .map(|ch| jit_box(HK_STRING, ch.to_string()))
180 .collect();
181 jit_box(HK_ARRAY, JitArray::from_vec(chars))
182 }
183 "isEmpty" | "is_empty" => {
184 if s.is_empty() {
185 TAG_BOOL_TRUE
186 } else {
187 TAG_BOOL_FALSE
188 }
189 }
190 "repeat" => {
191 if args.is_empty() {
192 return receiver_bits;
193 }
194 if is_number(args[0]) {
195 let count = unbox_number(args[0]) as usize;
196 let repeated = s.repeat(count);
197 return jit_box(HK_STRING, repeated);
198 }
199 receiver_bits
200 }
201 "padStart" | "pad_start" => {
202 if args.is_empty() {
203 return receiver_bits;
204 }
205 let target_len = if is_number(args[0]) {
206 unbox_number(args[0]) as usize
207 } else {
208 return receiver_bits;
209 };
210 let pad_char = if args.len() > 1 && is_heap_kind(args[1], HK_STRING) {
211 let pad_s = jit_unbox::<String>(args[1]);
212 pad_s.chars().next().unwrap_or(' ')
213 } else {
214 ' '
215 };
216 if s.len() >= target_len {
217 return receiver_bits;
218 }
219 let padding: String = std::iter::repeat_n(pad_char, target_len - s.len()).collect();
220 let padded = format!("{}{}", padding, s);
221 jit_box(HK_STRING, padded)
222 }
223 "padEnd" | "pad_end" => {
224 if args.is_empty() {
225 return receiver_bits;
226 }
227 let target_len = if is_number(args[0]) {
228 unbox_number(args[0]) as usize
229 } else {
230 return receiver_bits;
231 };
232 let pad_char = if args.len() > 1 && is_heap_kind(args[1], HK_STRING) {
233 let pad_s = jit_unbox::<String>(args[1]);
234 pad_s.chars().next().unwrap_or(' ')
235 } else {
236 ' '
237 };
238 if s.len() >= target_len {
239 return receiver_bits;
240 }
241 let padding: String = std::iter::repeat_n(pad_char, target_len - s.len()).collect();
242 let padded = format!("{}{}", s, padding);
243 jit_box(HK_STRING, padded)
244 }
245 _ => TAG_NULL,
246 }
247 }
248}