mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
refactor: 属性元数据与闭包 cell 等四小项下沉对象子模块
This commit is contained in:
@@ -8,47 +8,17 @@
|
||||
|
||||
use crate::value::JsValue;
|
||||
|
||||
mod cell;
|
||||
mod native_fn;
|
||||
mod prop_meta;
|
||||
mod string;
|
||||
mod typed_array;
|
||||
|
||||
pub use cell::Cell;
|
||||
pub use native_fn::NativeFnPtr;
|
||||
pub use prop_meta::{PropAttributes, PropIndex, PropMetaEntry};
|
||||
pub use string::{ConsNode, JsString};
|
||||
|
||||
/// 原生函数指针的类型安全不透明包装。
|
||||
///
|
||||
/// 以 `*const ()` 存储而非具体 `fn` 类型,使 `oxide_types` 无需依赖
|
||||
/// `oxide_vm::Vm`。`oxide_vm` 中的调用方经 `NativeFnPtr::call_with` 转回
|
||||
/// `NativeFn`——transmute 被限制在单个泛型辅助函数中。
|
||||
///
|
||||
/// # Safety 不变量
|
||||
///
|
||||
/// `NativeFnPtr` 必须总是由合法的 `NativeFn` 函数指针(裸 `fn` 项或函数项
|
||||
/// 强制转换——**不是**闭包)创建。指针永不为空。`Send + Sync` 安全是因为
|
||||
/// 函数项指针天然线程安全(不含数据)。
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct NativeFnPtr(pub *const ());
|
||||
|
||||
impl NativeFnPtr {
|
||||
/// 包装裸函数指针。指针必须指向合法的 `NativeFn` 函数项。
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` 必须是类型为 `fn(&mut Vm, &[u8]) -> NativeResult` 的非空函数指针
|
||||
/// 转成的 `*const ()`。使用任何其它指针值在调用时是 UB。
|
||||
#[inline(always)]
|
||||
pub unsafe fn from_raw(ptr: *const ()) -> Self {
|
||||
debug_assert!(!ptr.is_null(), "NativeFnPtr must not be null");
|
||||
Self(ptr)
|
||||
}
|
||||
|
||||
/// 返回底层裸指针。
|
||||
#[inline(always)]
|
||||
pub fn as_ptr(self) -> *const () {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: 函数项指针不含可变状态,可安全跨线程共享。
|
||||
unsafe impl Send for NativeFnPtr {}
|
||||
unsafe impl Sync for NativeFnPtr {}
|
||||
pub use typed_array::TypedArrayKind;
|
||||
|
||||
/// 形状标识符(对象 header 低位 24 位)。
|
||||
pub type ShapeId = u32;
|
||||
@@ -56,191 +26,14 @@ pub type ShapeId = u32;
|
||||
/// dense 属性向量长度的硬上限,防止索引失控导致内存膨胀。
|
||||
pub const MAX_DENSE_PROPS: usize = 1_000_000;
|
||||
|
||||
/// TypedArray 的元素类型,决定 `bytes_per_element` 与内存视图的字节序解读。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum TypedArrayKind {
|
||||
Int8,
|
||||
Uint8,
|
||||
Uint8Clamped,
|
||||
Int16,
|
||||
Uint16,
|
||||
Int32,
|
||||
Uint32,
|
||||
Float32,
|
||||
Float64,
|
||||
BigInt64,
|
||||
BigUint64,
|
||||
}
|
||||
|
||||
impl TypedArrayKind {
|
||||
/// 每个元素的字节数(1/2/4/8)。
|
||||
pub const fn bytes_per_element(self) -> usize {
|
||||
match self {
|
||||
Self::Int8 | Self::Uint8 | Self::Uint8Clamped => 1,
|
||||
Self::Int16 | Self::Uint16 => 2,
|
||||
Self::Int32 | Self::Uint32 | Self::Float32 => 4,
|
||||
Self::Float64 | Self::BigInt64 | Self::BigUint64 => 8,
|
||||
}
|
||||
}
|
||||
|
||||
/// 对应的具体构造器名(如 `Int16Array`),供 `@@toStringTag` getter 返回。
|
||||
pub const fn name(self) -> &'static str {
|
||||
match self {
|
||||
Self::Int8 => "Int8Array",
|
||||
Self::Uint8 => "Uint8Array",
|
||||
Self::Uint8Clamped => "Uint8ClampedArray",
|
||||
Self::Int16 => "Int16Array",
|
||||
Self::Uint16 => "Uint16Array",
|
||||
Self::Int32 => "Int32Array",
|
||||
Self::Uint32 => "Uint32Array",
|
||||
Self::Float32 => "Float32Array",
|
||||
Self::Float64 => "Float64Array",
|
||||
Self::BigInt64 => "BigInt64Array",
|
||||
Self::BigUint64 => "BigUint64Array",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 属性描述符标志位集合,压缩在单个 `u8` 中。
|
||||
/// 定长对象头 + 堆外数据指针的 JS 普通/外来对象。
|
||||
///
|
||||
/// 位定义:bit0 = writable,bit1 = enumerable,bit2 = configurable。
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct PropAttributes(pub u8);
|
||||
|
||||
impl PropAttributes {
|
||||
/// writable 标志位(bit0)。
|
||||
pub const WRITABLE: u8 = 0b001;
|
||||
/// enumerable 标志位(bit1)。
|
||||
pub const ENUMERABLE: u8 = 0b010;
|
||||
/// configurable 标志位(`0b100`)。
|
||||
pub const CONFIGURABLE: u8 = 0b100;
|
||||
/// 数据属性默认描述符:三标志全开。
|
||||
pub const DEFAULT_DATA: Self = Self(Self::WRITABLE | Self::ENUMERABLE | Self::CONFIGURABLE);
|
||||
|
||||
/// 由三个布尔标志构造描述符。
|
||||
pub const fn new(writable: bool, enumerable: bool, configurable: bool) -> Self {
|
||||
let mut bits = 0;
|
||||
if writable {
|
||||
bits |= Self::WRITABLE;
|
||||
}
|
||||
if enumerable {
|
||||
bits |= Self::ENUMERABLE;
|
||||
}
|
||||
if configurable {
|
||||
bits |= Self::CONFIGURABLE;
|
||||
}
|
||||
Self(bits)
|
||||
}
|
||||
|
||||
/// 是否 writable。
|
||||
pub const fn writable(self) -> bool {
|
||||
self.0 & Self::WRITABLE != 0
|
||||
}
|
||||
|
||||
/// 是否 enumerable。
|
||||
pub const fn enumerable(self) -> bool {
|
||||
self.0 & Self::ENUMERABLE != 0
|
||||
}
|
||||
|
||||
/// 是否 configurable。
|
||||
pub const fn configurable(self) -> bool {
|
||||
self.0 & Self::CONFIGURABLE != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// 单个属性的元数据条目。
|
||||
/// 内联字段:`header`(shape_id + 一组标志位)、`type_tag`(外来对象种类)、
|
||||
/// `proto`、`generation` 等;dense 属性向量、属性元数据、native payload 与
|
||||
/// upvalue cell 列表以裸指针挂在堆上,由 VM / GC 维护。对象可分配在
|
||||
/// session arena(`Epoch`)或全局堆(`Arc`),通过
|
||||
/// `is_session_epoch` 位区分。
|
||||
///
|
||||
/// 数据属性仅用 `attributes`;访问器属性额外携带 getter / setter
|
||||
/// 的 [`JsValue`] 与 `is_accessor = true` 标记。`hole` 标记数组元素被删除
|
||||
/// 后保留的稀疏空洞(数组元素区存在性判定依据)。
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct PropMetaEntry {
|
||||
pub attributes: PropAttributes,
|
||||
pub get: JsValue,
|
||||
pub set: JsValue,
|
||||
pub is_accessor: bool,
|
||||
pub hole: bool,
|
||||
}
|
||||
|
||||
impl PropMetaEntry {
|
||||
/// 构造数据属性条目。
|
||||
pub fn data(attributes: PropAttributes) -> Self {
|
||||
Self {
|
||||
attributes,
|
||||
get: JsValue::undefined(),
|
||||
set: JsValue::undefined(),
|
||||
is_accessor: false,
|
||||
hole: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// 构造访问器属性条目(getter/setter 可为 `undefined`)。
|
||||
pub fn accessor(get: JsValue, set: JsValue, attributes: PropAttributes) -> Self {
|
||||
Self {
|
||||
attributes,
|
||||
get,
|
||||
set,
|
||||
is_accessor: true,
|
||||
hole: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// 构造数组元素删除后的 hole 标记条目。
|
||||
pub fn hole() -> Self {
|
||||
Self {
|
||||
attributes: PropAttributes::DEFAULT_DATA,
|
||||
get: JsValue::undefined(),
|
||||
set: JsValue::undefined(),
|
||||
is_accessor: false,
|
||||
hole: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否数组元素 hole 标记(删除后保留的稀疏空洞)。
|
||||
pub fn is_hole(&self) -> bool {
|
||||
self.hole
|
||||
}
|
||||
}
|
||||
|
||||
/// 可转换为 dense 属性下标的值。
|
||||
///
|
||||
/// 为 `u8` / `u16` / `u32` / `usize` / 非负 `i32` 实现,统一属性向量
|
||||
/// 下标参数的类型。
|
||||
pub trait PropIndex {
|
||||
fn to_u32(self) -> u32;
|
||||
}
|
||||
|
||||
impl PropIndex for u8 {
|
||||
fn to_u32(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl PropIndex for u16 {
|
||||
fn to_u32(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl PropIndex for u32 {
|
||||
fn to_u32(self) -> u32 {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl PropIndex for usize {
|
||||
fn to_u32(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl PropIndex for i32 {
|
||||
fn to_u32(self) -> u32 {
|
||||
debug_assert!(self >= 0, "property index must be non-negative");
|
||||
self.max(0) as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// 布局:
|
||||
/// header: u32 位
|
||||
/// \[0:23\] shape_id
|
||||
@@ -274,64 +67,6 @@ impl PropIndex for i32 {
|
||||
///
|
||||
/// 总计:112 字节
|
||||
/// 对齐:8 字节
|
||||
#[repr(C)]
|
||||
pub struct Cell {
|
||||
pub value: JsValue,
|
||||
pub flags: u8,
|
||||
pub _pad: [u8; 7],
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
/// 已初始化标志(TDZ / 未赋值检测)。
|
||||
pub const INITIALIZED: u8 = 0x01;
|
||||
/// GC 标记位。
|
||||
pub const GC_MARK: u8 = 0x02;
|
||||
|
||||
/// 构造 cell,`initialized` 决定是否立即置 [`INITIALIZED`](Cell::INITIALIZED) 位。
|
||||
pub fn new(value: JsValue, initialized: bool) -> Self {
|
||||
Cell {
|
||||
value,
|
||||
flags: if initialized { Self::INITIALIZED } else { 0 },
|
||||
_pad: [0; 7],
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否已初始化。
|
||||
pub fn is_initialized(&self) -> bool {
|
||||
self.flags & Self::INITIALIZED != 0
|
||||
}
|
||||
|
||||
/// 设置 / 清除已初始化标志。
|
||||
pub fn set_initialized(&mut self, val: bool) {
|
||||
if val {
|
||||
self.flags |= Self::INITIALIZED;
|
||||
} else {
|
||||
self.flags &= !Self::INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否被 GC 标记。
|
||||
pub fn is_gc_marked(&self) -> bool {
|
||||
self.flags & Self::GC_MARK != 0
|
||||
}
|
||||
|
||||
/// 设置 / 清除 GC 标记。
|
||||
pub fn set_gc_mark(&mut self, marked: bool) {
|
||||
if marked {
|
||||
self.flags |= Self::GC_MARK;
|
||||
} else {
|
||||
self.flags &= !Self::GC_MARK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 定长对象头 + 堆外数据指针的 JS 普通/外来对象。
|
||||
///
|
||||
/// 内联字段:`header`(shape_id + 一组标志位)、`type_tag`(外来对象种类)、
|
||||
/// `proto`、`generation` 等;dense 属性向量、属性元数据、native payload 与
|
||||
/// upvalue cell 列表以裸指针挂在堆上,由 VM / GC 维护。对象可分配在
|
||||
/// session arena(`Epoch`)或全局堆(`Arc`),通过
|
||||
/// `is_session_epoch` 位区分。
|
||||
pub struct JsObject {
|
||||
header: u32,
|
||||
native_arg_count: u8,
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
//! 闭包共享 cell:JS 值 + 已初始化 / GC 标记位,定长 16 字节。
|
||||
//!
|
||||
//! cell 组成闭包的 upvalue 数组(对象 `upvalues` 裸指针区),随闭包释放;
|
||||
//! `flags` 为 1 字节位集加 7 字节固定填充,保证数组元素步长恒定。
|
||||
|
||||
use crate::value::JsValue;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Cell {
|
||||
pub value: JsValue,
|
||||
pub flags: u8,
|
||||
pub _pad: [u8; 7],
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
/// 已初始化标志(TDZ / 未赋值检测)。
|
||||
pub const INITIALIZED: u8 = 0x01;
|
||||
/// GC 标记位。
|
||||
pub const GC_MARK: u8 = 0x02;
|
||||
|
||||
/// 构造 cell,`initialized` 决定是否立即置 [`INITIALIZED`](Cell::INITIALIZED) 位。
|
||||
pub fn new(value: JsValue, initialized: bool) -> Self {
|
||||
Cell {
|
||||
value,
|
||||
flags: if initialized { Self::INITIALIZED } else { 0 },
|
||||
_pad: [0; 7],
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否已初始化。
|
||||
pub fn is_initialized(&self) -> bool {
|
||||
self.flags & Self::INITIALIZED != 0
|
||||
}
|
||||
|
||||
/// 设置 / 清除已初始化标志。
|
||||
pub fn set_initialized(&mut self, val: bool) {
|
||||
if val {
|
||||
self.flags |= Self::INITIALIZED;
|
||||
} else {
|
||||
self.flags &= !Self::INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否被 GC 标记。
|
||||
pub fn is_gc_marked(&self) -> bool {
|
||||
self.flags & Self::GC_MARK != 0
|
||||
}
|
||||
|
||||
/// 设置 / 清除 GC 标记。
|
||||
pub fn set_gc_mark(&mut self, marked: bool) {
|
||||
if marked {
|
||||
self.flags |= Self::GC_MARK;
|
||||
} else {
|
||||
self.flags &= !Self::GC_MARK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//! 原生函数指针的类型安全不透明包装。
|
||||
//!
|
||||
//! 以 `*const ()` 存储而非具体 `fn` 类型,使本 crate 无需依赖 `oxide_vm`;
|
||||
//! 指针必须由合法的 `NativeFn` 函数项创建且永不为空,`Send + Sync` 依赖
|
||||
//! 函数项指针天然线程安全。
|
||||
|
||||
/// 原生函数指针的类型安全不透明包装。
|
||||
///
|
||||
/// 以 `*const ()` 存储而非具体 `fn` 类型,使 `oxide_types` 无需依赖
|
||||
/// `oxide_vm::Vm`。`oxide_vm` 中的调用方经 `NativeFnPtr::call_with` 转回
|
||||
/// `NativeFn`——transmute 被限制在单个泛型辅助函数中。
|
||||
///
|
||||
/// # Safety 不变量
|
||||
///
|
||||
/// `NativeFnPtr` 必须总是由合法的 `NativeFn` 函数指针(裸 `fn` 项或函数项
|
||||
/// 强制转换——**不是**闭包)创建。指针永不为空。`Send + Sync` 安全是因为
|
||||
/// 函数项指针天然线程安全(不含数据)。
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct NativeFnPtr(pub *const ());
|
||||
|
||||
impl NativeFnPtr {
|
||||
/// 包装裸函数指针。指针必须指向合法的 `NativeFn` 函数项。
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` 必须是类型为 `fn(&mut Vm, &[u8]) -> NativeResult` 的非空函数指针
|
||||
/// 转成的 `*const ()`。使用任何其它指针值在调用时是 UB。
|
||||
#[inline(always)]
|
||||
pub unsafe fn from_raw(ptr: *const ()) -> Self {
|
||||
debug_assert!(!ptr.is_null(), "NativeFnPtr must not be null");
|
||||
Self(ptr)
|
||||
}
|
||||
|
||||
/// 返回底层裸指针。
|
||||
#[inline(always)]
|
||||
pub fn as_ptr(self) -> *const () {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: 函数项指针不含可变状态,可安全跨线程共享。
|
||||
unsafe impl Send for NativeFnPtr {}
|
||||
unsafe impl Sync for NativeFnPtr {}
|
||||
@@ -0,0 +1,147 @@
|
||||
//! 属性元数据:描述符标志、数据/访问器属性条目与 dense 下标转换。
|
||||
//!
|
||||
//! `PropAttributes` 把三个描述符标志压缩进单个 `u8` 位集;`PropMetaEntry` 承载
|
||||
//! 单个属性的元数据(数据 / 访问器两形态 + 数组空洞标记);`PropIndex` 统一
|
||||
//! 可作 dense 属性下标的整数类型。
|
||||
|
||||
use crate::value::JsValue;
|
||||
|
||||
/// 属性描述符标志位集合,压缩在单个 `u8` 中。
|
||||
///
|
||||
/// 位定义:bit0 = writable,bit1 = enumerable,bit2 = configurable。
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct PropAttributes(pub u8);
|
||||
|
||||
impl PropAttributes {
|
||||
/// writable 标志位(bit0)。
|
||||
pub const WRITABLE: u8 = 0b001;
|
||||
/// enumerable 标志位(bit1)。
|
||||
pub const ENUMERABLE: u8 = 0b010;
|
||||
/// configurable 标志位(`0b100`)。
|
||||
pub const CONFIGURABLE: u8 = 0b100;
|
||||
/// 数据属性默认描述符:三标志全开。
|
||||
pub const DEFAULT_DATA: Self = Self(Self::WRITABLE | Self::ENUMERABLE | Self::CONFIGURABLE);
|
||||
|
||||
/// 由三个布尔标志构造描述符。
|
||||
pub const fn new(writable: bool, enumerable: bool, configurable: bool) -> Self {
|
||||
let mut bits = 0;
|
||||
if writable {
|
||||
bits |= Self::WRITABLE;
|
||||
}
|
||||
if enumerable {
|
||||
bits |= Self::ENUMERABLE;
|
||||
}
|
||||
if configurable {
|
||||
bits |= Self::CONFIGURABLE;
|
||||
}
|
||||
Self(bits)
|
||||
}
|
||||
|
||||
/// 是否 writable。
|
||||
pub const fn writable(self) -> bool {
|
||||
self.0 & Self::WRITABLE != 0
|
||||
}
|
||||
|
||||
/// 是否 enumerable。
|
||||
pub const fn enumerable(self) -> bool {
|
||||
self.0 & Self::ENUMERABLE != 0
|
||||
}
|
||||
|
||||
/// 是否 configurable。
|
||||
pub const fn configurable(self) -> bool {
|
||||
self.0 & Self::CONFIGURABLE != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// 单个属性的元数据条目。
|
||||
///
|
||||
/// 数据属性仅用 `attributes`;访问器属性额外携带 getter / setter
|
||||
/// 的 [`JsValue`] 与 `is_accessor = true` 标记。`hole` 标记数组元素被删除
|
||||
/// 后保留的稀疏空洞(数组元素区存在性判定依据)。
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct PropMetaEntry {
|
||||
pub attributes: PropAttributes,
|
||||
pub get: JsValue,
|
||||
pub set: JsValue,
|
||||
pub is_accessor: bool,
|
||||
pub hole: bool,
|
||||
}
|
||||
|
||||
impl PropMetaEntry {
|
||||
/// 构造数据属性条目。
|
||||
pub fn data(attributes: PropAttributes) -> Self {
|
||||
Self {
|
||||
attributes,
|
||||
get: JsValue::undefined(),
|
||||
set: JsValue::undefined(),
|
||||
is_accessor: false,
|
||||
hole: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// 构造访问器属性条目(getter/setter 可为 `undefined`)。
|
||||
pub fn accessor(get: JsValue, set: JsValue, attributes: PropAttributes) -> Self {
|
||||
Self {
|
||||
attributes,
|
||||
get,
|
||||
set,
|
||||
is_accessor: true,
|
||||
hole: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// 构造数组元素删除后的 hole 标记条目。
|
||||
pub fn hole() -> Self {
|
||||
Self {
|
||||
attributes: PropAttributes::DEFAULT_DATA,
|
||||
get: JsValue::undefined(),
|
||||
set: JsValue::undefined(),
|
||||
is_accessor: false,
|
||||
hole: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否数组元素 hole 标记(删除后保留的稀疏空洞)。
|
||||
pub fn is_hole(&self) -> bool {
|
||||
self.hole
|
||||
}
|
||||
}
|
||||
|
||||
/// 可转换为 dense 属性下标的值。
|
||||
///
|
||||
/// 为 `u8` / `u16` / `u32` / `usize` / 非负 `i32` 实现,统一属性向量
|
||||
/// 下标参数的类型。
|
||||
pub trait PropIndex {
|
||||
fn to_u32(self) -> u32;
|
||||
}
|
||||
|
||||
impl PropIndex for u8 {
|
||||
fn to_u32(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl PropIndex for u16 {
|
||||
fn to_u32(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl PropIndex for u32 {
|
||||
fn to_u32(self) -> u32 {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl PropIndex for usize {
|
||||
fn to_u32(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl PropIndex for i32 {
|
||||
fn to_u32(self) -> u32 {
|
||||
debug_assert!(self >= 0, "property index must be non-negative");
|
||||
self.max(0) as u32
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//! TypedArray 元素种类:定每元素字节数与具体构造器名。
|
||||
//!
|
||||
//! 10 个变体与具体 TypedArray 构造器一一对应;`name()` 供
|
||||
//! `@@toStringTag` getter 返回构造器名。
|
||||
|
||||
/// TypedArray 的元素类型,决定 `bytes_per_element` 与内存视图的字节序解读。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum TypedArrayKind {
|
||||
Int8,
|
||||
Uint8,
|
||||
Uint8Clamped,
|
||||
Int16,
|
||||
Uint16,
|
||||
Int32,
|
||||
Uint32,
|
||||
Float32,
|
||||
Float64,
|
||||
BigInt64,
|
||||
BigUint64,
|
||||
}
|
||||
|
||||
impl TypedArrayKind {
|
||||
/// 每个元素的字节数(1/2/4/8)。
|
||||
pub const fn bytes_per_element(self) -> usize {
|
||||
match self {
|
||||
Self::Int8 | Self::Uint8 | Self::Uint8Clamped => 1,
|
||||
Self::Int16 | Self::Uint16 => 2,
|
||||
Self::Int32 | Self::Uint32 | Self::Float32 => 4,
|
||||
Self::Float64 | Self::BigInt64 | Self::BigUint64 => 8,
|
||||
}
|
||||
}
|
||||
|
||||
/// 对应的具体构造器名(如 `Int16Array`),供 `@@toStringTag` getter 返回。
|
||||
pub const fn name(self) -> &'static str {
|
||||
match self {
|
||||
Self::Int8 => "Int8Array",
|
||||
Self::Uint8 => "Uint8Array",
|
||||
Self::Uint8Clamped => "Uint8ClampedArray",
|
||||
Self::Int16 => "Int16Array",
|
||||
Self::Uint16 => "Uint16Array",
|
||||
Self::Int32 => "Int32Array",
|
||||
Self::Uint32 => "Uint32Array",
|
||||
Self::Float32 => "Float32Array",
|
||||
Self::Float64 => "Float64Array",
|
||||
Self::BigInt64 => "BigInt64Array",
|
||||
Self::BigUint64 => "BigUint64Array",
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user