Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Number and bool #12

Merged
merged 13 commits into from
Nov 21, 2023
13 changes: 13 additions & 0 deletions notes/table.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ group(() => {
]).map(f))
})('Number')

group(() => {
/** @type {(t: unknown) => readonly[unknown, string]} */
const f = t => [t, typeof t]
console.table([
f(15),
f("Hello world!"),
f(true),
f([]),
f({}),
f(null),
])
})('typeof')

export default {
print,
}
8 changes: 3 additions & 5 deletions src/bit_subset64.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::marker::PhantomData;

use crate::{const_assert::const_assert, container::Clean, ptr_subset::PtrSubset};
use crate::{const_assert::const_assert, ptr_subset::PtrSubset};

/// A bit subset of `u64`.
///
Expand Down Expand Up @@ -87,8 +85,8 @@ impl BitSubset64 {
)
}
#[inline(always)]
pub const fn ptr_subset<T: Clean>(self) -> PtrSubset<T> {
PtrSubset(self, PhantomData)
pub const fn ptr_subset<T>(self) -> PtrSubset<T> {
PtrSubset::new(self)
}
}

Expand Down
38 changes: 21 additions & 17 deletions src/container.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
use std::alloc::{GlobalAlloc, Layout, System};
use std::{
alloc::{GlobalAlloc, Layout, System},
ptr::read,
};

#[repr(C)]
pub struct Container<T: Clean> {
pub struct Container<T> {
counter: usize,
value: T,
pub value: T,
size: usize,
}

pub trait Clean {
fn clean(&mut self);
}
pub const DROP: bool = false;
pub const CLONE: bool = true;

impl<T: Clean> Container<T> {
impl<T> Container<T> {
const LAYOUT: Layout = Layout::new::<Container<T>>();
pub unsafe fn alloc() -> *mut Self {
System.alloc_zeroed(Self::LAYOUT) as *mut Self
}
pub unsafe fn update<const ADD: bool>(p: *mut Self) {
let r = &mut *p;
let c = r.counter;
if ADD {
r.counter += 1;
} else {
if r.counter != 0 {
r.counter -= 1;
return;
}
r.value.clean();
System.dealloc(p as *mut u8, Self::LAYOUT);
r.counter = c + 1;
return;
}
if c != 0 {
r.counter = c - 1;
return;
}
drop(read(&r.value));
System.dealloc(p as *mut u8, Self::LAYOUT);
}
}

Expand All @@ -36,8 +40,8 @@ mod test {

struct DebugClean(*mut usize);

impl Clean for DebugClean {
fn clean(&mut self) {
impl Drop for DebugClean {
fn drop(&mut self) {
unsafe {
*self.0 += 1;
}
Expand Down
33 changes: 33 additions & 0 deletions src/container_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::ops::Deref;

use crate::container::{Container, CLONE, DROP};

struct Ref<T>(*mut Container<T>);

impl<T> Ref<T> {
pub fn new(p: &mut Container<T>) -> Self {
unsafe { Container::update::<CLONE>(p) };
Self(p)
}
}

impl<T> Clone for Ref<T> {
fn clone(&self) -> Self {
Self::new(unsafe { &mut *self.0 })
}
}

impl<T> Drop for Ref<T> {
fn drop(&mut self) {
unsafe {
Container::update::<DROP>(self.0);
}
}
}

impl<T> Deref for Ref<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &(*self.0).value }
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod bit_subset64;
mod const_assert;
mod container;
mod container_ref;
mod number;
mod object;
mod ptr_subset;
mod string16;
mod value;
mod value_type;
34 changes: 34 additions & 0 deletions src/number.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
use crate::const_assert::const_assert;

// compatible with `f64`
pub const INFINITY: u64 = 0x7FF0_0000_0000_0000;
pub const NAN: u64 = 0x7FF8_0000_0000_0000;
pub const NEG_INFINITY: u64 = 0xFFF0_0000_0000_0000;
pub const E: u64 = 0x7FF0_0000_0000_0000;
pub const EF: u64 = 0x7FFF_FFFF_FFFF_FFFF;

pub const fn is_valid(v: u64) -> bool {
v & E != E || v & EF == INFINITY || v == NAN
}

pub const fn check(v: u64) {
const_assert(is_valid(v));
}

#[cfg(test)]
mod test {
Expand All @@ -14,4 +26,26 @@ mod test {
assert_eq!(f64::NAN.to_bits(), NAN);
assert_eq!(f64::NEG_INFINITY.to_bits(), NEG_INFINITY);
}

#[test]
fn test_check() {
check(0);
check(1);
check(INFINITY);
check(NAN);
check(NEG_INFINITY);
assert_eq!((0.0f64 / 0.0).to_bits(), NAN);
}

#[test]
#[should_panic]
fn test_nan_panic() {
check(0x7FF0_00F0_0500_0001);
}

#[test]
#[should_panic]
fn test_nan_panic2() {
check(0xFFFA_FF96_5534_5781);
}
}
8 changes: 1 addition & 7 deletions src/object.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
use crate::container::Clean;

pub struct Object {}

impl Clean for Object {
fn clean(&mut self) {}
}
pub struct Object();
29 changes: 17 additions & 12 deletions src/ptr_subset.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
use std::marker::PhantomData;

use crate::{
bit_subset64::BitSubset64,
container::{Clean, Container},
};
use crate::{bit_subset64::BitSubset64, const_assert::const_assert, container::Container};

pub struct PtrSubset<T: Clean>(pub BitSubset64, pub PhantomData<T>);
pub struct PtrSubset<T>(BitSubset64, PhantomData<T>);

impl<T: Clean> PtrSubset<T> {
pub fn update<const ADD: bool>(&self, v: u64) {
let v = v & self.0.superposition();
if v == 0 {
return;
}
// 49 bits for now
pub const PTR_SUBSET_SUPERPOSITION: u64 = 0x1_FFFF_FFFF_FFFF;

impl<T> PtrSubset<T> {
#[inline(always)]
pub fn update<const ADD: bool>(&self, p: u64) {
unsafe {
Container::update::<ADD>(v as *mut Container<T>);
Container::update::<ADD>(p as *mut Container<T>);
}
}
#[inline(always)]
pub const fn subset(&self) -> BitSubset64 {
self.0
}
pub const fn new(subset: BitSubset64) -> Self {
const_assert(subset.superposition() == PTR_SUBSET_SUPERPOSITION);
Self(subset, PhantomData)
}
}
8 changes: 1 addition & 7 deletions src/string16.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
use crate::container::Clean;

pub struct String16 {}

impl Clean for String16 {
fn clean(&mut self) {}
}
pub struct String16();
Loading