Skip to content

Commit

Permalink
feat(vm): Merge the Tag and Data variants of ValueRef
Browse files Browse the repository at this point in the history
`ValueRef` shouldn't expose implementation details such as that
  • Loading branch information
Marwes committed Jun 19, 2017
1 parent cdf41ba commit ed7330d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 25 deletions.
4 changes: 2 additions & 2 deletions examples/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ impl<'vm> Getable<'vm> for Wrap<StatusCode> {
fn from_value(_: &'vm Thread, value: Variants) -> Option<Self> {
use hyper::StatusCode::*;
match value.as_ref() {
ValueRef::Tag(tag) => {
Some(Wrap(match tag {
ValueRef::Data(data) => {
Some(Wrap(match data.tag() {
0 => Ok,
1 => NotFound,
2 => InternalServerError,
Expand Down
9 changes: 3 additions & 6 deletions vm/src/api/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ impl<'de, 't, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 't> {
ValueRef::Float(_) => self.deserialize_f64(visitor),
ValueRef::Int(_) => self.deserialize_i64(visitor),
ValueRef::String(ref s) => visitor.visit_borrowed_str(s),
ValueRef::Tag(_) => self.deserialize_enum("", &[], visitor),
ValueRef::Userdata(_) |
ValueRef::Internal => Err(Self::Error::custom("Cant deserialize type")),
}
Expand All @@ -153,7 +152,7 @@ impl<'de, 't, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 't> {
V: Visitor<'de>,
{
match self.input.as_ref() {
ValueRef::Tag(t) => visitor.visit_bool(t != 0),
ValueRef::Data(data) => visitor.visit_bool(data.tag() != 0),
_ => Err(Self::Error::custom("Cant deserialize type")),
}
}
Expand Down Expand Up @@ -333,7 +332,7 @@ impl<'de, 't, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 't> {
_ => return Err(Self::Error::custom("Expected `Option` type")),
};
match self.input.as_ref() {
ValueRef::Tag(0) => visitor.visit_none(),
ValueRef::Data(data) if data.tag() == 0 => visitor.visit_none(),
ValueRef::Data(data) if data.tag() == 1 => {
visitor.visit_some(&mut Deserializer {
state: self.state.clone(),
Expand All @@ -350,7 +349,7 @@ impl<'de, 't, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 't> {
V: Visitor<'de>,
{
match self.input.as_ref() {
ValueRef::Tag(0) => visitor.visit_unit(),
ValueRef::Data(data) if data.tag() == 0 => visitor.visit_unit(),
_ => Err(Self::Error::custom("Cant deserialize type")),
}
}
Expand Down Expand Up @@ -583,7 +582,6 @@ impl<'a, 'b, 'de, 't> de::Deserializer<'de> for &'b mut Enum<'a, 'de, 't> {
{
match self.de.input.as_ref() {
ValueRef::Data(data) => visitor.visit_u32(data.tag()),
ValueRef::Tag(tag) => visitor.visit_u32(tag),
_ => Err(Self::Error::custom("Cant deserialize tag")),
}
}
Expand All @@ -594,7 +592,6 @@ impl<'a, 'b, 'de, 't> de::Deserializer<'de> for &'b mut Enum<'a, 'de, 't> {
{
let tag = match self.de.input.as_ref() {
ValueRef::Data(data) => data.tag(),
ValueRef::Tag(tag) => tag,
_ => return Err(Self::Error::custom("Cant deserialize tag")),
};
let typ = resolve::remove_aliases_cow(self.de.state.env, self.de.typ);
Expand Down
50 changes: 33 additions & 17 deletions vm/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ pub enum ValueRef<'a> {
String(&'a str),
Data(Data<'a>),
Array(ArrayRef<'a>),
Tag(VmTag),
Userdata(&'a vm::Userdata),
Internal,
}
Expand All @@ -59,7 +58,6 @@ impl<'a, 'b> PartialEq<ValueRef<'b>> for ValueRef<'a> {
(&Float(l), &Float(r)) => l == r,
(&String(l), &String(r)) => l == r,
(&Data(l), &Data(r)) => l == r,
(&Tag(l), &Tag(r)) => l == r,
_ => false,
}
}
Expand All @@ -82,10 +80,10 @@ impl<'a> ValueRef<'a> {
Value::Int(i) => ValueRef::Int(i),
Value::Float(f) => ValueRef::Float(f),
Value::String(s) => ValueRef::String(forget_lifetime(&*s)),
Value::Data(data) => ValueRef::Data(Data(forget_lifetime(&*data))),
Value::Data(data) => ValueRef::Data(Data(DataInner::Data(forget_lifetime(&*data)))),
Value::Tag(tag) => ValueRef::Data(Data(DataInner::Tag(tag))),
Value::Array(array) => ValueRef::Array(ArrayRef(forget_lifetime(&*array))),
Value::Userdata(data) => ValueRef::Userdata(forget_lifetime(&**data)),
Value::Tag(tag) => ValueRef::Tag(tag),
Value::Thread(_) |
Value::Function(_) |
Value::Closure(_) |
Expand All @@ -95,31 +93,52 @@ impl<'a> ValueRef<'a> {
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Data<'a>(&'a DataStruct);
enum DataInner<'a> {
Tag(VmTag),
Data(&'a DataStruct),
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Data<'a>(DataInner<'a>);

impl<'a> Data<'a> {
pub fn tag(&self) -> VmTag {
self.0.tag
match self.0 {
DataInner::Tag(tag) => tag,
DataInner::Data(data) => data.tag,
}
}

pub fn len(&self) -> usize {
self.0.fields.len()
match self.0 {
DataInner::Tag(_) => 0,
DataInner::Data(data) => data.fields.len(),
}
}

pub fn get(&self, index: usize) -> Option<ValueRef<'a>> {
self.0.fields.get(index).map(ValueRef::new)
match self.0 {
DataInner::Tag(_) => None,
DataInner::Data(data) => data.fields.get(index).map(ValueRef::new),
}
}

pub fn get_variants(&self, index: usize) -> Option<Variants<'a>> {
unsafe { self.0.fields.get(index).map(|v| Variants::new(v)) }
match self.0 {
DataInner::Tag(_) => None,
DataInner::Data(data) => unsafe { data.fields.get(index).map(|v| Variants::new(v)) },
}
}

// Retrieves the field `name` from this record
pub fn lookup_field(&self, thread: &Thread, name: &str) -> Option<Variants<'a>> {
unsafe {
thread.lookup_field(self.0, name).ok().map(|v| {
Variants::with_root(v, self.0)
})
match self.0 {
DataInner::Tag(_) => None,
DataInner::Data(data) => unsafe {
thread.lookup_field(data, name).ok().map(|v| {
Variants::with_root(v, data)
})
},
}
}
}
Expand Down Expand Up @@ -557,8 +576,7 @@ impl<'vm> Pushable<'vm> for bool {
impl<'vm> Getable<'vm> for bool {
fn from_value(_: &'vm Thread, value: Variants) -> Option<bool> {
match value.as_ref() {
ValueRef::Tag(1) => Some(true),
ValueRef::Tag(0) => Some(false),
ValueRef::Data(data) => Some(data.tag() == 1),
_ => None,
}
}
Expand Down Expand Up @@ -588,7 +606,6 @@ impl<'vm> Getable<'vm> for Ordering {
fn from_value(_: &'vm Thread, value: Variants) -> Option<Ordering> {
let tag = match value.as_ref() {
ValueRef::Data(data) => data.tag(),
ValueRef::Tag(tag) => tag,
_ => return None,
};
match tag {
Expand Down Expand Up @@ -805,7 +822,6 @@ impl<'vm, T: Getable<'vm>> Getable<'vm> for Option<T> {
T::from_value(vm, data.get_variants(0).unwrap()).map(Some)
}
}
ValueRef::Tag(0) => Some(None),
_ => None,
}
}
Expand Down

0 comments on commit ed7330d

Please sign in to comment.