Repository: martinohmann/hcl-rs (rust)

Issue:
error deserializing index access operator
`let _: Body = crate::from_str("a = b[\"c\"]").unwrap()` fails to deserialize the index access operator.

Expected behaviour is to deserialize this just fine.

```
Message { msg: "unknown variant `Index`, expected one of `Null`, `Bool`, `Number`, `String`, `Array`, `Object`, `TemplateExpr`, `VariableExpr`, `ElementAccess`, `FuncCall`, `SubExpr`, `Raw`", location: None }
```

Pull request description:
fix: use correct deserializer for index element access
Fixes #66.

Patch:
diff --git a/src/structure/de.rs b/src/structure/de.rs
index c19652c..cc8bdc6 100644
--- a/src/structure/de.rs
+++ b/src/structure/de.rs
@@ -423,7 +423,6 @@ impl<'de> de::Deserializer<'de> for ElementAccessOperator {
         string bytes byte_buf option unit unit_struct newtype_struct seq
         tuple tuple_struct map struct identifier ignored_any
     }
-    impl_deserialize_enum!();
 
     fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
     where
@@ -439,6 +438,18 @@ impl<'de> de::Deserializer<'de> for ElementAccessOperator {
             ElementAccessOperator::LegacyIndex(index) => visitor.visit_u64(index),
         }
     }
+
+    fn deserialize_enum<V>(
+        self,
+        _name: &'static str,
+        _variants: &'static [&'static str],
+        visitor: V,
+    ) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        visitor.visit_enum(self)
+    }
 }
 
 impl VariantName for ElementAccessOperator {
@@ -453,6 +464,58 @@ impl VariantName for ElementAccessOperator {
     }
 }
 
+impl<'de> de::EnumAccess<'de> for ElementAccessOperator {
+    type Error = Error;
+    type Variant = Self;
+
+    fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
+    where
+        T: de::DeserializeSeed<'de>,
+    {
+        let variant_name = self.variant_name();
+
+        seed.deserialize(variant_name.into_deserializer())
+            .map(|variant| (variant, self))
+    }
+}
+
+impl<'de> de::VariantAccess<'de> for ElementAccessOperator {
+    type Error = Error;
+
+    fn unit_variant(self) -> Result<(), Self::Error> {
+        de::Deserialize::deserialize(self)
+    }
+
+    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
+    where
+        T: de::DeserializeSeed<'de>,
+    {
+        match self {
+            ElementAccessOperator::Index(expr) => seed.deserialize(expr.into_deserializer()),
+            ElementAccessOperator::GetAttr(ident) => seed.deserialize(ident.into_deserializer()),
+            value => seed.deserialize(value.into_deserializer()),
+        }
+    }
+
+    fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.into_deserializer().deserialize_seq(visitor)
+    }
+
+    fn struct_variant<V>(
+        self,
+        _fields: &'static [&'static str],
+        visitor: V,
+    ) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.into_deserializer().deserialize_map(visitor)
+    }
+}
+
 impl<'de> IntoDeserializer<'de, Error> for FuncCall {
     type Deserializer = MapAccessDeserializer<FuncCallAccess>;
 


Test patch:
diff --git a/src/de/tests.rs b/src/de/tests.rs
index 8c99311..60fc3b3 100644
--- a/src/de/tests.rs
+++ b/src/de/tests.rs
@@ -344,3 +344,17 @@ fn issue_44() {
 
     assert_eq!(config, expected);
 }
+
+#[test]
+fn issue_66() {
+    let body: Body = crate::from_str("a = b[\"c\"]").unwrap();
+
+    let expected = Body::builder()
+        .add_attribute((
+            "a",
+            ElementAccess::new(Identifier::new("b"), Expression::String(String::from("c"))),
+        ))
+        .build();
+
+    assert_eq!(body, expected);
+}