diff --git a/src/object/types.rs b/src/object/types.rs index b98e4b549..e766cbaf4 100644 --- a/src/object/types.rs +++ b/src/object/types.rs @@ -16,29 +16,6 @@ impl ExtractType for T { } } -impl ExtractType for Vec> { - fn extract(value: &Tagged) -> Result { - let name = std::any::type_name::(); - trace!(" Extracting {:?} for Vec<{}>", value, name); - - match value.item() { - Value::List(items) => { - let mut out = vec![]; - - for item in items { - out.push(T::extract(item)?.tagged(item.tag())); - } - - Ok(out) - } - other => Err(ShellError::type_error( - "Vec", - other.type_name().tagged(value.tag()), - )), - } - } -} - impl ExtractType for (T, U) { fn extract(value: &Tagged) -> Result<(T, U), ShellError> { let t_name = std::any::type_name::(); diff --git a/src/parser/deserializer.rs b/src/parser/deserializer.rs index 9f753ced8..66f83c656 100644 --- a/src/parser/deserializer.rs +++ b/src/parser/deserializer.rs @@ -25,6 +25,13 @@ impl<'de> ConfigDeserializer<'de> { } } + pub fn push_val(&mut self, val: Tagged) { + self.stack.push(DeserializerItem { + key_struct_field: None, + val, + }); + } + pub fn push(&mut self, name: &'static str) -> Result<(), ShellError> { let value: Option> = if name == "rest" { let positional = self.call.args.slice_from(self.position); @@ -74,7 +81,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> { V::Value::extract(&value.val) } - forward_to_deserialize_any! { bool option seq } + forward_to_deserialize_any! { bool option } fn deserialize_i8(self, _visitor: V) -> Result where @@ -193,7 +200,24 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> { { unimplemented!("deserialize_newtype_struct") } + fn deserialize_seq(mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let value = self.pop(); + trace!(" Extracting {:?} for vec", value.val); + match value.val.into_parts() { + (Value::List(items), _) => { + let de = SeqDeserializer::new(&mut self, items.into_iter()); + visitor.visit_seq(de) + } + (other, tag) => Err(ShellError::type_error( + "Vec", + other.type_name().tagged(tag), + )), + } + } fn deserialize_tuple(self, _len: usize, _visitor: V) -> Result where V: Visitor<'de>, @@ -268,6 +292,42 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> { } } +struct SeqDeserializer<'a, 'de: 'a, I: Iterator>> { + de: &'a mut ConfigDeserializer<'de>, + vals: I, +} + +impl<'a, 'de: 'a, I: Iterator>> SeqDeserializer<'a, 'de, I> { + fn new(de: &'a mut ConfigDeserializer<'de>, vals: I) -> Self { + SeqDeserializer { + de, + vals, + } + } +} + +impl<'a, 'de: 'a, I: Iterator>> de::SeqAccess<'de> for SeqDeserializer<'a, 'de, I> { + type Error = ShellError; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + let next = if let Some(next) = self.vals.next() { + next + } else { + return Ok(None); + }; + + self.de.push_val(next); + seed.deserialize(&mut *self.de).map(Some) + } + + fn size_hint(&self) -> Option { + return self.vals.size_hint().1; + } +} + struct StructDeserializer<'a, 'de: 'a> { de: &'a mut ConfigDeserializer<'de>, fields: &'static [&'static str],