1use std::fmt;
8use std::fmt::{Debug, Formatter, Write as _};
9use std::marker::PhantomData;
10
11use mozjs::jsapi::JSClass;
12
13use crate::utils::ArrayVec;
14
15pub const MAX_PROTO_CHAIN_LENGTH: usize = 8;
16
17pub trait TypeIdWrap: private::Sealed + 'static {}
18
19mod private {
20 use std::any::TypeId;
21
22 pub trait Sealed: 'static {
23 fn type_id(&self) -> TypeId;
24 }
25
26 impl<T: 'static> Sealed for super::TypeIdWrapper<T> {
27 fn type_id(&self) -> TypeId {
28 TypeId::of::<T>()
29 }
30 }
31}
32
33pub struct TypeIdWrapper<T: 'static> {
34 _private: PhantomData<T>,
35}
36
37impl<T: 'static> TypeIdWrapper<T> {
38 pub const fn new() -> TypeIdWrapper<T> {
39 TypeIdWrapper { _private: PhantomData }
40 }
41}
42
43impl<T: 'static> Default for TypeIdWrapper<T> {
44 fn default() -> TypeIdWrapper<T> {
45 TypeIdWrapper::new()
46 }
47}
48
49impl<T: 'static> TypeIdWrap for TypeIdWrapper<T> {}
50
51unsafe impl<T: 'static> Send for TypeIdWrapper<T> {}
52
53unsafe impl<T: 'static> Sync for TypeIdWrapper<T> {}
54
55pub type PrototypeChain = ArrayVec<MAX_PROTO_CHAIN_LENGTH, &'static (dyn TypeIdWrap + Send + Sync)>;
56
57#[repr(C)]
58pub struct NativeClass {
59 pub base: JSClass,
60 pub prototype_chain: PrototypeChain,
61}
62
63impl Debug for NativeClass {
64 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
65 struct ChainDebug {
66 len: usize,
67 }
68
69 impl Debug for ChainDebug {
70 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
71 f.write_str("[TypeIdWrapper; ")?;
72 self.len.fmt(f)?;
73 f.write_char('/')?;
74 MAX_PROTO_CHAIN_LENGTH.fmt(f)?;
75 f.write_char(']')
76 }
77 }
78
79 f.debug_struct("NativeClass")
80 .field("base", &self.base)
81 .field("prototype_chain", &ChainDebug { len: self.prototype_chain.len() })
82 .finish()
83 }
84}