ul_next/javascript/
string.rs1use core::fmt;
2use std::{ffi::c_char, sync::Arc};
3
4use crate::Library;
5
6pub struct JSString {
10 pub(crate) internal: ul_sys::JSStringRef,
11 lib: Arc<Library>,
12}
13
14impl JSString {
15 pub(crate) fn from_raw(lib: Arc<Library>, string: ul_sys::JSStringRef) -> Self {
16 assert!(!string.is_null());
17
18 Self {
19 internal: string,
20 lib,
21 }
22 }
23
24 pub(crate) fn copy_from_raw(
25 lib: Arc<Library>,
26 string: *mut ul_sys::OpaqueJSString,
27 ) -> JSString {
28 assert!(!string.is_null());
29
30 let string = unsafe { lib.ultralight().JSStringRetain(string) };
31
32 Self {
33 internal: string,
34 lib,
35 }
36 }
37
38 pub fn new(lib: Arc<Library>, string: &str) -> Self {
40 let cstring = std::ffi::CString::new(string).unwrap();
41
42 let string = unsafe {
43 lib.ultralight()
44 .JSStringCreateWithUTF8CString(cstring.as_ptr())
45 };
46
47 Self {
48 internal: string,
49 lib,
50 }
51 }
52
53 pub fn is_empty(&self) -> bool {
55 self.len() == 0
56 }
57
58 pub fn len(&self) -> usize {
60 unsafe { self.lib.ultralight().JSStringGetLength(self.internal) }
61 }
62}
63
64impl From<&JSString> for String {
65 fn from(string: &JSString) -> Self {
66 let max_size = unsafe {
67 string
68 .lib
69 .ultralight()
70 .JSStringGetMaximumUTF8CStringSize(string.internal)
71 };
72
73 let mut buffer: Vec<u8> = Vec::with_capacity(max_size);
74
75 unsafe {
76 let actual_size = string.lib.ultralight().JSStringGetUTF8CString(
77 string.internal,
78 buffer.as_mut_ptr().cast::<c_char>(),
79 max_size,
80 );
81 buffer.set_len(actual_size - 1);
82 }
83
84 String::from_utf8(buffer).unwrap()
85 }
86}
87
88impl Clone for JSString {
89 fn clone(&self) -> Self {
90 let string = unsafe { self.lib.ultralight().JSStringRetain(self.internal) };
91
92 Self {
93 internal: string,
94 lib: self.lib.clone(),
95 }
96 }
97}
98
99impl fmt::Debug for JSString {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 String::from(self).fmt(f)
102 }
103}
104
105impl fmt::Display for JSString {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 String::from(self).fmt(f)
108 }
109}
110
111impl Drop for JSString {
112 fn drop(&mut self) {
113 unsafe {
114 self.lib.ultralight().JSStringRelease(self.internal);
115 }
116 }
117}