mirror of
https://github.com/Noratrieb/terustform.git
synced 2026-01-14 16:35:11 +01:00
to_value proc macro
This commit is contained in:
parent
7d28815065
commit
f3c37539f0
4 changed files with 57 additions and 47 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use terustform::{
|
use terustform::{
|
||||||
framework::{
|
framework::{
|
||||||
|
|
@ -6,7 +6,7 @@ use terustform::{
|
||||||
provider::Provider,
|
provider::Provider,
|
||||||
AttrPath, DResult, Diagnostics, StringValue, ValueModel,
|
AttrPath, DResult, Diagnostics, StringValue, ValueModel,
|
||||||
},
|
},
|
||||||
values::{Value, ValueKind},
|
values::Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
@ -28,6 +28,13 @@ impl Provider for ExampleProvider {
|
||||||
|
|
||||||
struct ExampleDataSource {}
|
struct ExampleDataSource {}
|
||||||
|
|
||||||
|
#[derive(terustform::DataSourceModel)]
|
||||||
|
struct ExampleDataSourceModel {
|
||||||
|
name: StringValue,
|
||||||
|
meow: StringValue,
|
||||||
|
id: StringValue,
|
||||||
|
}
|
||||||
|
|
||||||
impl DataSource for ExampleDataSource {
|
impl DataSource for ExampleDataSource {
|
||||||
fn name(&self, provider_name: &str) -> String {
|
fn name(&self, provider_name: &str) -> String {
|
||||||
format!("{provider_name}_kitty")
|
format!("{provider_name}_kitty")
|
||||||
|
|
@ -66,7 +73,7 @@ impl DataSource for ExampleDataSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(&self, config: Value) -> DResult<Value> {
|
fn read(&self, config: Value) -> DResult<Value> {
|
||||||
let model = ExampleDataSourceModel::from_value(config, &AttrPath::root())?;
|
let mut model = ExampleDataSourceModel::from_value(config, &AttrPath::root())?;
|
||||||
|
|
||||||
let StringValue::Known(name_str) = &model.name else {
|
let StringValue::Known(name_str) = &model.name else {
|
||||||
return Err(Diagnostics::error_string(
|
return Err(Diagnostics::error_string(
|
||||||
|
|
@ -75,23 +82,9 @@ impl DataSource for ExampleDataSource {
|
||||||
};
|
};
|
||||||
let meow = format!("mrrrrr i am {name_str}");
|
let meow = format!("mrrrrr i am {name_str}");
|
||||||
|
|
||||||
Ok(Value::Known(ValueKind::Object(BTreeMap::from([
|
model.meow = StringValue::Known(meow);
|
||||||
("name".to_owned(), model.name.to_value()),
|
model.id = StringValue::Known("0".to_owned());
|
||||||
(
|
|
||||||
"meow".to_owned(),
|
Ok(model.to_value())
|
||||||
Value::Known(ValueKind::String(meow)),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"id".to_owned(),
|
|
||||||
Value::Known(ValueKind::String("0".to_owned())),
|
|
||||||
),
|
|
||||||
]))))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(terustform::DataSourceModel)]
|
|
||||||
struct ExampleDataSourceModel {
|
|
||||||
name: StringValue,
|
|
||||||
meow: StringValue,
|
|
||||||
id: StringValue,
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ fn data_source_model_inner(
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
let terustform = quote!(::terustform::__derive_private);
|
let tf = quote!(::terustform::__derive_private);
|
||||||
|
|
||||||
let fields = fields
|
let fields = fields
|
||||||
.named
|
.named
|
||||||
|
|
@ -44,61 +44,74 @@ fn data_source_model_inner(
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
|
||||||
let field_extractions = fields.iter().map(|(name, ty)| {
|
let field_extractions = fields.iter().map(|(name, ty)| {
|
||||||
let name_str = proc_macro2::Literal::string(&name.to_string());
|
let name_str = proc_macro2::Literal::string(&name.to_string());
|
||||||
quote! {
|
quote! {
|
||||||
let #terustform::Some(#name) = obj.remove(#name_str) else {
|
let #tf::Some(#name) = obj.remove(#name_str) else {
|
||||||
return #terustform::Err(
|
return #tf::Err(
|
||||||
#terustform::Diagnostics::error_string(
|
#tf::Diagnostics::error_string(
|
||||||
format!("Expected property '{}', which was not present", #name_str),
|
format!("Expected property '{}', which was not present", #name_str),
|
||||||
).with_path(path.clone())
|
).with_path(path.clone())
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let #name = <#ty as #terustform::ValueModel>::from_value(
|
let #name = <#ty as #tf::ValueModel>::from_value(
|
||||||
#name,
|
#name,
|
||||||
&path.append_attribute_name(#terustform::ToOwned::to_owned(#name_str))
|
&path.append_attribute_name(#tf::ToOwned::to_owned(#name_str))
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let constructor_fields = fields.iter().map(|(name, _)| quote! { #name, });
|
let constructor_fields = fields.iter().map(|(name, _)| quote! { #name, });
|
||||||
|
|
||||||
|
let to_value_fields = fields.iter().map(|(name, ty)| {
|
||||||
|
let name_str = proc_macro2::Literal::string(&name.to_string());
|
||||||
|
|
||||||
|
quote! { (#name_str, <#ty as #tf::ValueModel>::to_value(self.#name)), }
|
||||||
|
});
|
||||||
|
|
||||||
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
|
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics #terustform::ValueModel
|
impl #impl_generics #tf::ValueModel
|
||||||
for #struct_name #type_generics #where_clause
|
for #struct_name #type_generics #where_clause
|
||||||
{
|
{
|
||||||
fn from_value(v: #terustform::Value, path: &#terustform::AttrPath) -> #terustform::DResult<Self> {
|
fn from_value(v: #tf::Value, path: &#tf::AttrPath) -> #tf::DResult<Self> {
|
||||||
match v {
|
match v {
|
||||||
#terustform::BaseValue::Unknown => {
|
#tf::BaseValue::Unknown => {
|
||||||
return #terustform::Err(#terustform::Diagnostics::with_path(
|
return #tf::Err(#tf::Diagnostics::with_path(
|
||||||
#terustform::Diagnostics::error_string(#terustform::ToOwned::to_owned("Expected object, found unknown value")),
|
#tf::Diagnostics::error_string(#tf::ToOwned::to_owned("Expected object, found unknown value")),
|
||||||
#terustform::Clone::clone(&path),
|
#tf::Clone::clone(&path),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
#terustform::BaseValue::Null => {
|
#tf::BaseValue::Null => {
|
||||||
return #terustform::Err(#terustform::Diagnostics::with_path(
|
return #tf::Err(#tf::Diagnostics::with_path(
|
||||||
#terustform::Diagnostics::error_string(#terustform::ToOwned::to_owned("Expected object, found null value")),
|
#tf::Diagnostics::error_string(#tf::ToOwned::to_owned("Expected object, found null value")),
|
||||||
#terustform::Clone::clone(&path),
|
#tf::Clone::clone(&path),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
#terustform::BaseValue::Known(#terustform::ValueKind::Object(mut obj)) => {
|
#tf::BaseValue::Known(#tf::ValueKind::Object(mut obj)) => {
|
||||||
#(#field_extractions)*
|
#(#field_extractions)*
|
||||||
|
|
||||||
Ok(#struct_name {
|
Ok(#struct_name {
|
||||||
#(#constructor_fields)*
|
#(#constructor_fields)*
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
#terustform::BaseValue::Known(v) => {
|
#tf::BaseValue::Known(v) => {
|
||||||
return #terustform::Err(#terustform::Diagnostics::with_path(
|
return #tf::Err(#tf::Diagnostics::with_path(
|
||||||
#terustform::Diagnostics::error_string(format!("Expected object, found {} value", v.diagnostic_type_str())),
|
#tf::Diagnostics::error_string(format!("Expected object, found {} value", v.diagnostic_type_str())),
|
||||||
#terustform::Clone::clone(&path),
|
#tf::Clone::clone(&path),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_value(self) -> #tf::Value {
|
||||||
|
#tf::new_object(
|
||||||
|
[
|
||||||
|
#(#to_value_fields)*
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,9 +90,7 @@ impl<T> BaseValue<T> {
|
||||||
pub trait ValueModel: Sized {
|
pub trait ValueModel: Sized {
|
||||||
fn from_value(v: Value, path: &AttrPath) -> DResult<Self>;
|
fn from_value(v: Value, path: &AttrPath) -> DResult<Self>;
|
||||||
|
|
||||||
fn to_value(self) -> Value {
|
fn to_value(self) -> Value;
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueModel for StringValue {
|
impl ValueModel for StringValue {
|
||||||
|
|
|
||||||
|
|
@ -108,5 +108,11 @@ pub mod __derive_private {
|
||||||
AttrPath, AttrPathSegment, BaseValue, DResult, Diagnostics, ValueModel,
|
AttrPath, AttrPathSegment, BaseValue, DResult, Diagnostics, ValueModel,
|
||||||
};
|
};
|
||||||
pub use crate::values::{Value, ValueKind};
|
pub use crate::values::{Value, ValueKind};
|
||||||
pub use {Clone, Result::Err, Option::Some, ToOwned};
|
pub use {Clone, Option::Some, Result::Err, ToOwned};
|
||||||
|
|
||||||
|
pub fn new_object<const N: usize>(elems: [(&str, Value); N]) -> Value {
|
||||||
|
Value::Known(ValueKind::Object(std::collections::BTreeMap::from_iter(
|
||||||
|
elems.into_iter().map(|(k, v)| (k.to_owned(), v)),
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue