use crate::{
context::Ctx,
value::{self, rf::JsStringRef},
Error, Result,
};
use rquickjs_sys as qjs;
use std::{ffi::CStr, mem, ptr};
#[derive(Debug, Clone, PartialEq)]
pub struct String<'js>(JsStringRef<'js>);
impl<'js> String<'js> {
pub(crate) unsafe fn new(ctx: Ctx<'js>, v: qjs::JSValue) -> Self {
String(JsStringRef::from_js_value(ctx, v))
}
pub(crate) fn to_js_value(&self) -> qjs::JSValue {
self.0.to_js_value()
}
pub fn to_str(&self) -> Result<&str> {
unsafe {
let c_str = qjs::JS_ToCString(self.0.ctx.ctx, self.to_js_value());
if c_str == ptr::null_mut() {
return Err(Error::Unknown);
}
Ok(CStr::from_ptr(c_str).to_str()?)
}
}
pub fn from_str(ctx: Ctx<'js>, s: &str) -> Result<Self> {
unsafe {
let len = s.len();
let bytes = mem::transmute(s.as_ptr());
let js_val = qjs::JS_NewStringLen(ctx.ctx, bytes, len as u64);
let js_val = value::handle_exception(ctx, js_val)?;
assert_eq!(js_val.tag, qjs::JS_TAG_STRING as i64);
Ok(String::new(ctx, js_val))
}
}
}
#[cfg(test)]
mod test {
use crate::*;
#[test]
fn js_value_string_from_javascript() {
let rt = Runtime::new().unwrap();
let ctx = Context::full(&rt).unwrap();
ctx.with(|ctx| {
let val = ctx.eval::<Value, _>(" 'foo bar baz' ");
if let Ok(Value::String(x)) = val {
assert_eq!(x.to_str(), Ok("foo bar baz"))
} else {
panic!();
};
});
}
}