hcl-rs
hcl-rs copied to clipboard
unknown variant `${identifier.attr.subattr}`, expected one of `Null`, `Bool`, `Number`...
I ran into a seemingly complex edge case where deserialisation fails when an untagged enum is used together with deserialize_with
. In the following example:
#![allow(unused)]
use serde::Deserialize;
use serde::Deserializer;
use serde_json;
use anyhow;
use hcl;
pub fn de_transform<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where
D: Deserializer<'de>,
{
let expressions: Result<Vec<hcl::Expression>, _> = Deserialize::deserialize(deserializer);
if let Err(ref e) = expressions {
eprintln!("{:?}", e)
}
Ok(expressions?.iter().map(|expr| format!("Parsed expression: {}", expr.to_string())).collect::<Vec<_>>())
}
#[derive(Deserialize, Debug, Clone)]
struct A {
#[serde(deserialize_with = "de_transform")]
pub value_a: Vec<String>
}
#[derive(Deserialize, Debug, Clone)]
struct B {
#[serde(deserialize_with = "de_transform")]
pub value_b: Vec<String>
}
#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
enum Test {
A(A),
B(B),
}
#[derive(Deserialize, Debug, Clone)]
struct AX {
pub value_a: Vec<String>
}
#[derive(Deserialize, Debug, Clone)]
struct BX {
pub value_b: Vec<String>
}
#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
enum TestX {
AX(AX),
BX(BX),
}
fn main() -> anyhow::Result<()> {
let data = r#"
value_a = [ident.prop1.subprop1, ident.prop2.subprop2]
"#;
let get_body = || {
let body: Result<hcl::Body, _> = hcl::from_str(&data);
body
};
let body_1 = get_body();
// Will print body as expected
println!("{:?}", body_1);
let de_result_1: Result<A, _> = hcl::from_body(body_1?);
// Will print struct as expected
println!("{:?}", de_result_1);
let de_result_2: Result<TestX, _> = hcl::from_body(get_body()?);
// Will match enum case AX as expected
println!("{:?}", de_result_2);
// Will fail
let de_result_3: Result<Test, _> = hcl::from_body(get_body()?);
println!("{:?}", de_result_3);
Ok(())
}
de_transform
function will fail with:
Message { msg: "unknown variant `${ident.prop1.subprop1}`, expected one of `Null`, `Bool`, `Number`, `String`, `Array`, `Object`, `TemplateExpr`, `Variable`, `Traversal`, `FuncCall`, `Parenthesis`, `Conditional`, `Operation`, `ForExpr`, `Raw`", location: None }
I haven't been able to find a workaround unfortunately