diff --git a/implementations/rust/Cargo.toml b/implementations/rust/Cargo.toml index ca6e15a..d6b2b7c 100644 --- a/implementations/rust/Cargo.toml +++ b/implementations/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "preserves" -version = "0.4.0" +version = "0.5.0" authors = ["Tony Garnock-Jones "] edition = "2018" description = "Implementation of the Preserves serialization format via serde." diff --git a/implementations/rust/src/lib.rs b/implementations/rust/src/lib.rs index 24c6790..67565ba 100644 --- a/implementations/rust/src/lib.rs +++ b/implementations/rust/src/lib.rs @@ -216,7 +216,11 @@ mod value_tests { #[test] fn record_mut() { let says = VV::symbol("says").wrap(); let mut r = VV::record(says.clone(), vec![VV::from("Tony").wrap(), VV::from("Hello!").wrap()]); - r.as_record_mut().unwrap().1[0] = VV::from("Alice").wrap(); + assert_eq!(r.as_record_mut(Some(0)), None); + assert_eq!(r.as_record_mut(Some(1)), None); + assert!(r.as_record_mut(Some(2)).is_some()); + assert_eq!(r.as_record_mut(Some(3)), None); + r.as_record_mut(None).unwrap().1[0] = VV::from("Alice").wrap(); assert_eq!(r, VV::record(says, vec![VV::from("Alice").wrap(), VV::from("Hello!").wrap()])); } diff --git a/implementations/rust/src/value/de.rs b/implementations/rust/src/value/de.rs index 22db7d9..79ed467 100644 --- a/implementations/rust/src/value/de.rs +++ b/implementations/rust/src/value/de.rs @@ -342,7 +342,7 @@ impl<'a, 'de, N: NestedValue, D: 'de + Domain> EnumAccess<'de> for &'a mut De fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), D> where V: DeserializeSeed<'de> { - let (lp, _) = self.check(|v| v.as_record(), ExpectedKind::Record)?; + let (lp, _) = self.check(|v| v.as_record(None), ExpectedKind::Record(None))?; let v = self.input; self.input = N::boxunwrap(lp); let variant = seed.deserialize(&mut *self)?; @@ -359,18 +359,18 @@ impl<'a, 'de, N: NestedValue, D: 'de + Domain> VariantAccess<'de> for &'a mut } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de> { - let (_, fs) = self.input.value().as_record().unwrap(); + let (_, fs) = self.check(|v| v.as_record(Some(1)), ExpectedKind::Record(Some(1)))?; self.input = &fs[0]; seed.deserialize(&mut *self) } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: Visitor<'de> { - visitor.visit_seq(VecSeq::new(self, &self.input.value().as_record().unwrap().1)) + visitor.visit_seq(VecSeq::new(self, &self.input.value().as_record(None).unwrap().1)) } - fn struct_variant(self, _fields: &'static [&'static str], visitor: V) + fn struct_variant(self, fields: &'static [&'static str], visitor: V) -> Result where V: Visitor<'de> { - visitor.visit_seq(VecSeq::new(self, &self.input.value().as_record().unwrap().1)) + visitor.visit_seq(VecSeq::new(self, &self.input.value().as_record(Some(fields.len())).unwrap().1)) } } diff --git a/implementations/rust/src/value/error.rs b/implementations/rust/src/value/error.rs index f13a67e..188a969 100644 --- a/implementations/rust/src/value/error.rs +++ b/implementations/rust/src/value/error.rs @@ -22,7 +22,7 @@ pub enum ExpectedKind { ByteString, Symbol, - Record, + Record(Option), SimpleRecord(&'static str, Option), Option, Sequence, diff --git a/implementations/rust/src/value/value.rs b/implementations/rust/src/value/value.rs index 5760486..c228f6c 100644 --- a/implementations/rust/src/value/value.rs +++ b/implementations/rust/src/value/value.rs @@ -400,20 +400,28 @@ impl, D: Domain> Value { } pub fn is_record(&self) -> bool { - self.as_record().is_some() + self.as_record(None).is_some() } - pub fn as_record(&self) -> Option<&Record> { + pub fn as_record(&self, arity: Option) -> Option<&Record> { if let Value::Record(ref r) = *self { - Some(r) + match arity { + Some(expected) if r.1.len() == expected => Some(r), + Some(_other) => None, + None => Some(r) + } } else { None } } - pub fn as_record_mut(&mut self) -> Option<&mut Record> { + pub fn as_record_mut(&mut self, arity: Option) -> Option<&mut Record> { if let Value::Record(ref mut r) = *self { - Some(r) + match arity { + Some(expected) if r.1.len() == expected => Some(r), + Some(_other) => None, + None => Some(r) + } } else { None } @@ -428,14 +436,9 @@ impl, D: Domain> Value { } pub fn as_simple_record(&self, label: &str, arity: Option) -> Option<&Vec> { - self.as_record().and_then(|(lp,fs)| { + self.as_record(arity).and_then(|(lp,fs)| { match N::boxunwrap(lp).value() { - Value::Symbol(ref s) if s == label => - match arity { - Some(expected) if fs.len() == expected => Some(fs), - Some(_other) => None, - None => Some(fs) - } + Value::Symbol(ref s) if s == label => Some(fs), _ => None } })