Skip to main content

obeli_sk_boa_string/vtable/
static.rs

1use crate::iter::CodePointsIter;
2use crate::vtable::JsStringVTable;
3use crate::{JsStr, JsString, JsStringKind};
4use std::hash::{Hash, Hasher};
5use std::ptr::NonNull;
6
7/// A static string with vtable for uniform dispatch.
8#[derive(Debug, Clone, Copy)]
9#[repr(C)]
10pub struct StaticString {
11    /// Embedded `VTable` - must be the first field for vtable dispatch.
12    vtable: JsStringVTable,
13    /// The actual string data.
14    pub(crate) str: JsStr<'static>,
15}
16
17impl StaticString {
18    /// Create a new static string.
19    #[must_use]
20    pub const fn new(str: JsStr<'static>) -> Self {
21        Self {
22            vtable: JsStringVTable {
23                clone: static_clone,
24                drop: static_drop,
25                as_str: static_as_str,
26                code_points: static_code_points,
27                refcount: static_refcount,
28                len: str.len(),
29                kind: JsStringKind::Static,
30            },
31            str,
32        }
33    }
34}
35
36impl Hash for StaticString {
37    fn hash<H: Hasher>(&self, state: &mut H) {
38        self.str.hash(state);
39    }
40}
41
42impl PartialEq for StaticString {
43    fn eq(&self, other: &Self) -> bool {
44        self.str == other.str
45    }
46}
47
48impl Eq for StaticString {}
49
50impl std::borrow::Borrow<JsStr<'static>> for &'static StaticString {
51    fn borrow(&self) -> &JsStr<'static> {
52        &self.str
53    }
54}
55
56#[inline]
57pub(crate) fn static_clone(this: NonNull<JsStringVTable>) -> JsString {
58    // Static strings don't need ref counting, just copy the pointer.
59    // SAFETY: validated the string outside this function.
60    unsafe { JsString::from_ptr(this) }
61}
62
63#[inline]
64fn static_drop(_ptr: NonNull<JsStringVTable>) {
65    // Static strings don't need cleanup.
66}
67
68#[inline]
69fn static_as_str(this: NonNull<JsStringVTable>) -> JsStr<'static> {
70    // SAFETY: validated the string outside this function.
71    let this: &StaticString = unsafe { this.cast().as_ref() };
72    this.str
73}
74
75#[inline]
76fn static_code_points(this: NonNull<JsStringVTable>) -> CodePointsIter<'static> {
77    CodePointsIter::new(static_as_str(this))
78}
79
80#[inline]
81fn static_refcount(_ptr: NonNull<JsStringVTable>) -> Option<usize> {
82    // Static strings don't have refcount.
83    None
84}