mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
refactor(syntax): use NonMaxU32 for IDs (#4467)
`SymbolId` and `ReferenceId` are stored as `NonZeroU32`, but with a wrapper to make `u32::MAX` the illegal value, instead of `0`. Use the existing `nonmax` crate for this. Our current implementation uses `idx + 1` to avoid the zero value, whereas `nonmax` crate uses XOR `idx ^ u32::MAX`, which is a cheaper operation. Initially I made this change manually instead of pulling in a dependency, but it's a pain because it requires implementing `Debug` and `PartialOrd` by hand to handle the difference between the "actual" value and its stored representation. So I thought better to use a crate which does this for us.
This commit is contained in:
parent
82ba2a073f
commit
96fc94f61e
5 changed files with 52 additions and 24 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
|
@ -1153,6 +1153,12 @@ dependencies = [
|
|||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nonmax"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51"
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
|
|
@ -1758,6 +1764,7 @@ version = "0.22.0"
|
|||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"dashmap 6.0.1",
|
||||
"nonmax",
|
||||
"oxc_index",
|
||||
"oxc_span",
|
||||
"phf",
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ lazy_static = "1.4.0"
|
|||
memoffset = "0.9.1"
|
||||
miette = { version = "7.2.0", features = ["fancy-no-syscall"] }
|
||||
mimalloc = "0.1.42"
|
||||
nonmax = "0.5.5"
|
||||
num-bigint = "0.4.5"
|
||||
num-traits = "0.2.19"
|
||||
phf = "0.11.2"
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ bitflags = { workspace = true }
|
|||
rustc-hash = { workspace = true }
|
||||
dashmap = { workspace = true }
|
||||
phf = { workspace = true, features = ["macros"] }
|
||||
nonmax = { workspace = true }
|
||||
|
||||
ryu-js = { workspace = true, optional = true }
|
||||
serde = { workspace = true, features = ["derive"], optional = true }
|
||||
|
|
|
|||
|
|
@ -1,25 +1,31 @@
|
|||
use std::num::NonZeroU32;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use nonmax::NonMaxU32;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::Serialize;
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use oxc_index::Idx;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize))]
|
||||
pub struct ReferenceId(NonZeroU32);
|
||||
pub struct ReferenceId(NonMaxU32);
|
||||
|
||||
impl Idx for ReferenceId {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
// NB: We can't use `NonZeroU32::new_unchecked(idx as u32 + 1)`
|
||||
// because if `idx == u32::MAX`, `+ 1` would make it wrap around back to 0
|
||||
Self(NonZeroU32::new(idx as u32 + 1).unwrap())
|
||||
Self(NonMaxU32::new(idx as u32).unwrap())
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize - 1
|
||||
self.0.get() as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for ReferenceId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_u32(self.0.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,42 +1,55 @@
|
|||
use std::num::NonZeroU32;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use nonmax::NonMaxU32;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::Serialize;
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use oxc_index::Idx;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize))]
|
||||
pub struct SymbolId(NonZeroU32);
|
||||
pub struct SymbolId(NonMaxU32);
|
||||
|
||||
impl Idx for SymbolId {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
// NB: We can't use `NonZeroU32::new_unchecked(idx as u32 + 1)`
|
||||
// because if `idx == u32::MAX`, `+ 1` would make it wrap around back to 0
|
||||
Self(NonZeroU32::new(idx as u32 + 1).unwrap())
|
||||
Self(NonMaxU32::new(idx as u32).unwrap())
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize - 1
|
||||
self.0.get() as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for SymbolId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_u32(self.0.get())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize))]
|
||||
pub struct RedeclarationId(NonZeroU32);
|
||||
pub struct RedeclarationId(NonMaxU32);
|
||||
|
||||
impl Idx for RedeclarationId {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
// NB: We can't use `NonZeroU32::new_unchecked(idx as u32 + 1)`
|
||||
// because if `idx == u32::MAX`, `+ 1` would make it wrap around back to 0
|
||||
Self(NonZeroU32::new(idx as u32 + 1).unwrap())
|
||||
Self(NonMaxU32::new(idx as u32).unwrap())
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize - 1
|
||||
self.0.get() as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for RedeclarationId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_u32(self.0.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue