1#![feature(const_fn_transmute)]
2
3use std::{borrow::Borrow, ops::Deref};
4use std::convert::TryFrom;
5
6pub type JSParseError = boa::syntax::parser::ParseError;
7
8#[repr(transparent)]
11pub struct JSStr {
12 data: str,
13}
14
15pub struct JSString {
18 code: String,
19}
20
21pub trait JSTemplate {
22 fn render_template(&self) -> JSString;
23}
24
25
26impl JSStr {
27 pub fn new(js: &str) -> Result<&Self, JSParseError> {
46 let _ = boa::parse(js, false)?;
47
48 Ok(unsafe { JSStr::new_unchecked(js) })
50 }
51
52 pub const unsafe fn new_unchecked(js: &str) -> &Self {
54 std::mem::transmute(js)
56 }
57
58 pub fn as_str(&self) -> &str {
60 &self.data
61 }
62}
63
64impl<'a> TryFrom<&'a str> for &'a JSStr {
65 type Error = JSParseError;
66
67 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
68 JSStr::new(value)
69 }
70}
71
72impl AsRef<JSStr> for JSStr {
73 fn as_ref(&self) -> &JSStr {
74 self
75 }
76}
77
78impl AsRef<str> for JSStr {
79 fn as_ref(&self) -> &str {
80 &self.data
81 }
82}
83
84impl<'a> Into<&'a str> for &'a JSStr {
85 fn into(self) -> &'a str {
86 &self.data
87 }
88}
89
90impl ToOwned for JSStr {
91 type Owned = JSString;
92
93 fn to_owned(&self) -> Self::Owned {
94 unsafe {
96 JSString::new_unchecked(self.as_str().to_owned())
97 }
98 }
99}
100
101impl JSString {
102 pub fn new(code: String) -> Result<Self, JSParseError> {
103 let _ = JSStr::new(&code)?;
104 Ok(JSString{ code })
105 }
106
107 pub unsafe fn new_unchecked(code: String) -> Self {
108 JSString{ code }
109 }
110
111 pub fn into_string(self) -> String {
112 self.code
113 }
114}
115
116impl TryFrom<String> for JSString {
117 type Error = JSParseError;
118
119 fn try_from(value: String) -> Result<Self, Self::Error> {
120 JSString::new(value)
121 }
122}
123
124impl Into<String> for JSString {
125 fn into(self) -> String {
126 self.code
127 }
128}
129
130impl Borrow<JSStr> for JSString {
131 fn borrow(&self) -> &JSStr {
132 unsafe { JSStr::new_unchecked(&self.code) }
134 }
135}
136
137impl AsRef<JSStr> for JSString {
138 fn as_ref(&self) -> &JSStr {
139 self.borrow()
140 }
141}
142
143impl Deref for JSString {
144 type Target = JSStr;
145
146 fn deref(&self) -> &Self::Target {
147 unsafe { JSStr::new_unchecked(&self.code) }
149 }
150}