Skip to content

Commit

Permalink
feat(vm): Add conversions from integer types to SmallInteger (#59)
Browse files Browse the repository at this point in the history
This patch also makes `SmallInteger::from_i64_unchecked` a private
method, to prevent misuse.
  • Loading branch information
andreubotella authored Nov 1, 2023
1 parent c6fc727 commit 92e4056
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 7 deletions.
8 changes: 4 additions & 4 deletions nova_vm/src/ecmascript/types/language/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl From<SmallInteger> for Number {

impl From<i32> for Number {
fn from(value: i32) -> Self {
Number::Integer(SmallInteger::from_i64_unchecked(value as i64))
Number::Integer(SmallInteger::from(value))
}
}

Expand All @@ -50,7 +50,7 @@ impl From<i64> for Number {
let n = value
.min(SmallInteger::MAX_NUMBER)
.max(SmallInteger::MIN_NUMBER);
Number::Integer(SmallInteger::from_i64_unchecked(n))
Number::Integer(SmallInteger::try_from(n).unwrap())
}
}

Expand Down Expand Up @@ -257,7 +257,7 @@ impl Number {
}
Number::Integer(n) => {
let n = n.into_i64();
Number::Integer(SmallInteger::from_i64_unchecked(n.abs()))
Number::Integer(SmallInteger::try_from(n.abs()).unwrap())
}
Number::Float(n) => Number::Float(n.abs()),
}
Expand All @@ -279,7 +279,7 @@ impl Number {
let value = *agent.heap.get(n);
agent.heap.create(-value)
}
Number::Integer(n) => SmallInteger::from_i64_unchecked(-n.into_i64()).into(),
Number::Integer(n) => SmallInteger::try_from(-n.into_i64()).unwrap().into(),
Number::Float(n) => (-n).into(),
}
}
Expand Down
3 changes: 1 addition & 2 deletions nova_vm/src/ecmascript/types/language/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,7 @@ macro_rules! impl_value_from_n {
($size: ty) => {
impl From<$size> for Value {
fn from(value: $size) -> Self {
let n: i64 = value.into();
Value::Integer(SmallInteger::from_i64_unchecked(n))
Value::Integer(SmallInteger::from(value))
}
}
};
Expand Down
46 changes: 45 additions & 1 deletion nova_vm/src/engine/small_integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl SmallInteger {
}
}

pub fn from_i64_unchecked(value: i64) -> SmallInteger {
fn from_i64_unchecked(value: i64) -> SmallInteger {
debug_assert!((Self::MIN_BIGINT..=Self::MAX_BIGINT).contains(&value));
let bytes = i64::to_ne_bytes(value);

Expand Down Expand Up @@ -57,6 +57,50 @@ impl TryFrom<i64> for SmallInteger {
}
}

impl TryFrom<u64> for SmallInteger {
type Error = ();
fn try_from(value: u64) -> Result<Self, Self::Error> {
if value <= (Self::MAX_BIGINT as u64) {
Ok(Self::from_i64_unchecked(value as i64))
} else {
Err(())
}
}
}

macro_rules! from_numeric_type {
($numtype:ty) => {
// Checking at compile-time that $numtype fully fits within the range.
const _: () = {
assert!(
<$numtype>::MIN as i64 >= SmallInteger::MIN_BIGINT,
concat!(
stringify!($numtype),
" is outside of the SmallInteger range (min)"
)
);
assert!(
<$numtype>::MAX as i64 <= SmallInteger::MAX_BIGINT,
concat!(
stringify!($numtype),
" is outside of the SmallInteger range (max)"
)
);
};
impl From<$numtype> for SmallInteger {
fn from(value: $numtype) -> Self {
Self::from_i64_unchecked(i64::from(value))
}
}
};
}
from_numeric_type!(u8);
from_numeric_type!(i8);
from_numeric_type!(u16);
from_numeric_type!(i16);
from_numeric_type!(u32);
from_numeric_type!(i32);

impl From<SmallInteger> for i64 {
fn from(value: SmallInteger) -> Self {
let SmallInteger { data } = value;
Expand Down

0 comments on commit 92e4056

Please sign in to comment.