ion/class/
native.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use 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}