use crate::seqstring::global_bytes;
use crate::stack::{Stack, pop, push};
use crate::value::Value;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_string_empty(stack: Stack) -> Stack {
assert!(!stack.is_null(), "string_empty: stack is empty");
let (stack, value) = unsafe { pop(stack) };
match value {
Value::String(s) => {
let is_empty = s.as_bytes().is_empty();
unsafe { push(stack, Value::Bool(is_empty)) }
}
_ => panic!("string_empty: expected String on stack"),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_string_concat(stack: Stack) -> Stack {
assert!(!stack.is_null(), "string_concat: stack is empty");
let (stack, str2_val) = unsafe { pop(stack) };
assert!(!stack.is_null(), "string_concat: need two strings");
let (stack, str1_val) = unsafe { pop(stack) };
match (str1_val, str2_val) {
(Value::String(s1), Value::String(s2)) => {
let mut result = Vec::with_capacity(s1.as_bytes().len() + s2.as_bytes().len());
result.extend_from_slice(s1.as_bytes());
result.extend_from_slice(s2.as_bytes());
unsafe { push(stack, Value::String(global_bytes(result))) }
}
_ => panic!("string_concat: expected two strings on stack"),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_string_length(stack: Stack) -> Stack {
assert!(!stack.is_null(), "string_length: stack is empty");
let (stack, str_val) = unsafe { pop(stack) };
match str_val {
Value::String(s) => {
let len = s.as_str_or_empty().chars().count() as i64;
unsafe { push(stack, Value::Int(len)) }
}
_ => panic!("string_length: expected String on stack"),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_string_byte_length(stack: Stack) -> Stack {
assert!(!stack.is_null(), "string_byte_length: stack is empty");
let (stack, str_val) = unsafe { pop(stack) };
match str_val {
Value::String(s) => {
let len = s.as_bytes().len() as i64;
unsafe { push(stack, Value::Int(len)) }
}
_ => panic!("string_byte_length: expected String on stack"),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_string_equal(stack: Stack) -> Stack {
assert!(!stack.is_null(), "string_equal: stack is empty");
let (stack, str2_val) = unsafe { pop(stack) };
assert!(!stack.is_null(), "string_equal: need two strings");
let (stack, str1_val) = unsafe { pop(stack) };
match (str1_val, str2_val) {
(Value::String(s1), Value::String(s2)) => {
let equal = s1.as_bytes() == s2.as_bytes();
unsafe { push(stack, Value::Bool(equal)) }
}
_ => panic!("string_equal: expected two strings on stack"),
}
}