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

Added misaligned i128/u128 #144

Merged
merged 1 commit into from Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion minijinja/src/filters.rs
Expand Up @@ -492,7 +492,7 @@ mod builtins {
pub fn abs(value: Value) -> Result<Value, Error> {
match value.0 {
ValueRepr::I64(x) => Ok(Value::from(x.abs())),
ValueRepr::I128(x) => Ok(Value::from(x.abs())),
ValueRepr::I128(x) => Ok(Value::from(x.0.abs())),
ValueRepr::F64(x) => Ok(Value::from(x.abs())),
_ => Err(Error::new(
ErrorKind::InvalidOperation,
Expand Down
4 changes: 2 additions & 2 deletions minijinja/src/key/mod.rs
Expand Up @@ -82,11 +82,11 @@ impl<'a> Key<'a> {
ValueRepr::U64(v) => TryFrom::try_from(v)
.map(Key::I64)
.map_err(|_| ErrorKind::NonKey.into()),
ValueRepr::U128(v) => TryFrom::try_from(v)
ValueRepr::U128(v) => TryFrom::try_from(v.0)
.map(Key::I64)
.map_err(|_| ErrorKind::NonKey.into()),
ValueRepr::I64(v) => Ok(Key::I64(v)),
ValueRepr::I128(v) => TryFrom::try_from(v)
ValueRepr::I128(v) => TryFrom::try_from(v.0)
.map(Key::I64)
.map_err(|_| ErrorKind::NonKey.into()),
ValueRepr::F64(x) => {
Expand Down
24 changes: 19 additions & 5 deletions minijinja/src/value/argtypes.rs
Expand Up @@ -5,7 +5,9 @@ use std::ops::{Deref, DerefMut};

use crate::error::{Error, ErrorKind};
use crate::key::{Key, StaticKey};
use crate::value::{Arc, MapType, Object, StringType, Value, ValueKind, ValueRepr};
use crate::value::{
Arc, MapType, MisalignedI128, MisalignedU128, Object, StringType, Value, ValueKind, ValueRepr,
};
use crate::vm::State;

/// A utility trait that represents the return value of functions and filters.
Expand Down Expand Up @@ -291,17 +293,29 @@ macro_rules! value_from {
};
}

impl From<i128> for Value {
#[inline(always)]
fn from(val: i128) -> Self {
ValueRepr::I128(MisalignedI128(val)).into()
}
}

impl From<u128> for Value {
#[inline(always)]
fn from(val: u128) -> Self {
ValueRepr::U128(MisalignedU128(val)).into()
}
}

value_from!(bool, Bool);
value_from!(u8, U64);
value_from!(u16, U64);
value_from!(u32, U64);
value_from!(u64, U64);
value_from!(u128, U128);
value_from!(i8, I64);
value_from!(i16, I64);
value_from!(i32, I64);
value_from!(i64, I64);
value_from!(i128, I128);
value_from!(f32, F64);
value_from!(f64, F64);
value_from!(char, Char);
Expand Down Expand Up @@ -351,8 +365,8 @@ macro_rules! primitive_int_try_from {
ValueRepr::U64(val) => val,
// for the intention here see Key::from_borrowed_value
ValueRepr::F64(val) if (val as i64 as f64 == val) => val as i64,
ValueRepr::I128(val) => val,
ValueRepr::U128(val) => val,
ValueRepr::I128(val) => val.0,
ValueRepr::U128(val) => val.0,
});
}
}
Expand Down
36 changes: 24 additions & 12 deletions minijinja/src/value/mod.rs
Expand Up @@ -254,6 +254,18 @@ pub(crate) enum StringType {
Safe,
}

/// An `i128` that intentionally uses packed layout to ensure
/// that `ValueRepr` doesn't blow up in size.
#[derive(Copy, Clone)]
#[repr(packed)]
pub(crate) struct MisalignedI128(pub i128);

/// An `u128` that intentionally uses packed layout to ensure
/// that `ValueRepr` doesn't blow up in size.
#[derive(Copy, Clone)]
#[repr(packed)]
pub(crate) struct MisalignedU128(pub u128);

#[derive(Clone)]
pub(crate) enum ValueRepr {
Undefined,
Expand All @@ -263,8 +275,8 @@ pub(crate) enum ValueRepr {
F64(f64),
Char(char),
None,
U128(u128),
I128(i128),
U128(MisalignedU128),
I128(MisalignedI128),
String(Arc<String>, StringType),
Bytes(Arc<Vec<u8>>),
Seq(Arc<Vec<Value>>),
Expand All @@ -282,8 +294,8 @@ impl fmt::Debug for ValueRepr {
ValueRepr::F64(val) => fmt::Debug::fmt(val, f),
ValueRepr::Char(val) => fmt::Debug::fmt(val, f),
ValueRepr::None => write!(f, "None"),
ValueRepr::U128(val) => fmt::Debug::fmt(val, f),
ValueRepr::I128(val) => fmt::Debug::fmt(val, f),
ValueRepr::U128(val) => fmt::Debug::fmt(&{ val.0 }, f),
ValueRepr::I128(val) => fmt::Debug::fmt(&{ val.0 }, f),
ValueRepr::String(val, _) => fmt::Debug::fmt(val, f),
ValueRepr::Bytes(val) => fmt::Debug::fmt(val, f),
ValueRepr::Seq(val) => fmt::Debug::fmt(val, f),
Expand Down Expand Up @@ -359,7 +371,7 @@ impl fmt::Display for Value {
}
ValueRepr::Char(val) => write!(f, "{}", val),
ValueRepr::None => write!(f, "none"),
ValueRepr::I128(val) => write!(f, "{}", val),
ValueRepr::I128(val) => write!(f, "{}", { val.0 }),
ValueRepr::String(val, _) => write!(f, "{}", val),
ValueRepr::Bytes(val) => write!(f, "{}", String::from_utf8_lossy(val)),
ValueRepr::Seq(values) => {
Expand All @@ -382,7 +394,7 @@ impl fmt::Display for Value {
}
write!(f, "}}")
}
ValueRepr::U128(val) => write!(f, "{}", val),
ValueRepr::U128(val) => write!(f, "{}", { val.0 }),
ValueRepr::Dynamic(x) => write!(f, "{}", x),
}
}
Expand Down Expand Up @@ -523,9 +535,9 @@ impl Value {
match self.0 {
ValueRepr::Bool(val) => val,
ValueRepr::U64(x) => x != 0,
ValueRepr::U128(x) => x != 0,
ValueRepr::U128(x) => x.0 != 0,
ValueRepr::I64(x) => x != 0,
ValueRepr::I128(x) => x != 0,
ValueRepr::I128(x) => x.0 != 0,
ValueRepr::F64(x) => x != 0.0,
ValueRepr::Char(x) => x != '\x00',
ValueRepr::String(ref x, _) => !x.is_empty(),
Expand Down Expand Up @@ -820,11 +832,11 @@ impl Value {
ValueRepr::U64(v) => TryFrom::try_from(v)
.map(Key::I64)
.map_err(|_| ErrorKind::NonKey.into()),
ValueRepr::U128(v) => TryFrom::try_from(v)
ValueRepr::U128(v) => TryFrom::try_from(v.0)
.map(Key::I64)
.map_err(|_| ErrorKind::NonKey.into()),
ValueRepr::I64(v) => Ok(Key::I64(v)),
ValueRepr::I128(v) => TryFrom::try_from(v)
ValueRepr::I128(v) => TryFrom::try_from(v.0)
.map(Key::I64)
.map_err(|_| ErrorKind::NonKey.into()),
ValueRepr::Char(c) => Ok(Key::Char(c)),
Expand Down Expand Up @@ -898,8 +910,8 @@ impl Serialize for Value {
ValueRepr::Char(c) => serializer.serialize_char(c),
ValueRepr::None => serializer.serialize_unit(),
ValueRepr::Undefined => serializer.serialize_unit(),
ValueRepr::U128(u) => serializer.serialize_u128(u),
ValueRepr::I128(i) => serializer.serialize_i128(i),
ValueRepr::U128(u) => serializer.serialize_u128(u.0),
ValueRepr::I128(i) => serializer.serialize_i128(i.0),
ValueRepr::String(ref s, _) => serializer.serialize_str(s),
ValueRepr::Bytes(ref b) => serializer.serialize_bytes(b),
ValueRepr::Seq(ref elements) => elements.serialize(serializer),
Expand Down
8 changes: 4 additions & 4 deletions minijinja/src/value/ops.rs
Expand Up @@ -14,9 +14,9 @@ fn as_f64(value: &Value) -> Option<f64> {
Some(match value.0 {
ValueRepr::Bool(x) => x as i64 as f64,
ValueRepr::U64(x) => x as f64,
ValueRepr::U128(x) => x as f64,
ValueRepr::U128(x) => x.0 as f64,
ValueRepr::I64(x) => x as f64,
ValueRepr::I128(x) => x as f64,
ValueRepr::I128(x) => x.0 as f64,
ValueRepr::F64(x) => x,
_ => return None,
})
Expand All @@ -27,13 +27,13 @@ pub fn coerce(a: &Value, b: &Value) -> Option<CoerceResult> {
// equal mappings are trivial
(ValueRepr::U64(a), ValueRepr::U64(b)) => Some(CoerceResult::I128(*a as i128, *b as i128)),
(ValueRepr::U128(a), ValueRepr::U128(b)) => {
Some(CoerceResult::I128(*a as i128, *b as i128))
Some(CoerceResult::I128(a.0 as i128, b.0 as i128))
}
(ValueRepr::String(a, _), ValueRepr::String(b, _)) => {
Some(CoerceResult::String(a.to_string(), b.to_string()))
}
(ValueRepr::I64(a), ValueRepr::I64(b)) => Some(CoerceResult::I128(*a as i128, *b as i128)),
(ValueRepr::I128(a), ValueRepr::I128(b)) => Some(CoerceResult::I128(*a, *b)),
(ValueRepr::I128(a), ValueRepr::I128(b)) => Some(CoerceResult::I128(a.0, b.0)),
(ValueRepr::F64(a), ValueRepr::F64(b)) => Some(CoerceResult::F64(*a, *b)),

// are floats involved?
Expand Down
7 changes: 4 additions & 3 deletions minijinja/src/value/serialize.rs
Expand Up @@ -5,7 +5,8 @@ use serde::{ser, Serialize, Serializer};
use crate::error::Error;
use crate::key::{Key, KeySerializer, StaticKey};
use crate::value::{
Arc, MapType, StringType, Value, ValueMap, ValueRepr, VALUE_HANDLES, VALUE_HANDLE_MARKER,
Arc, MapType, MisalignedI128, MisalignedU128, StringType, Value, ValueMap, ValueRepr,
VALUE_HANDLES, VALUE_HANDLE_MARKER,
};

pub struct ValueSerializer;
Expand Down Expand Up @@ -43,7 +44,7 @@ impl Serializer for ValueSerializer {
}

fn serialize_i128(self, v: i128) -> Result<Value, Error> {
Ok(ValueRepr::I128(v).into())
Ok(ValueRepr::I128(MisalignedI128(v)).into())
}

fn serialize_u8(self, v: u8) -> Result<Value, Error> {
Expand All @@ -63,7 +64,7 @@ impl Serializer for ValueSerializer {
}

fn serialize_u128(self, v: u128) -> Result<Value, Error> {
Ok(ValueRepr::U128(v).into())
Ok(ValueRepr::U128(MisalignedU128(v)).into())
}

fn serialize_f32(self, v: f32) -> Result<Value, Error> {
Expand Down