git.delta.rocks / jrsonnet / refs/commits / f0c8338d487d

difftreelog

refactor split TypedObj derives

oqrkzkryYaroslav Bolyukin2026-03-22parent: #bd50dd1.patch.diff
in: master

5 files changed

modifiedcrates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/arr/spec.rs
+++ b/crates/jrsonnet-evaluator/src/arr/spec.rs
@@ -609,7 +609,7 @@
 	}
 }
 
-#[derive(Typed)]
+#[derive(Typed, IntoUntyped)]
 pub struct KeyValue {
 	key: IStr,
 	value: Thunk<Val>,
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
22
3use jrsonnet_gcmodule::Trace;3use jrsonnet_gcmodule::Trace;
4use jrsonnet_interner::{IBytes, IStr};4use jrsonnet_interner::{IBytes, IStr};
5pub use jrsonnet_macros::Typed;
6use jrsonnet_types::{ComplexValType, ValType};5use jrsonnet_types::{ComplexValType, ValType};
76
8use crate::{7use crate::{
14 ObjValue, ObjValueBuilder, Result, ResultExt, Thunk, Val,13 ObjValue, ObjValueBuilder, Result, ResultExt, Thunk, Val,
15};14};
15
16#[doc(hidden)]
17pub mod __typed_macro_prelude {
18 pub use ::jrsonnet_evaluator::{
19 error::{ErrorKind, Result as JrResult},
20 typed::{
21 CheckType, ComplexValType, FromUntyped, IntoUntyped, ParseTypedObj, SerializeTypedObj,
22 Typed,
23 },
24 IStr, ObjValue, ObjValueBuilder, State, Val,
25 };
26}
27pub use jrsonnet_macros::{FromUntyped, IntoUntyped, Typed};
1628
17#[derive(Trace)]29#[derive(Trace)]
18struct ThunkFromUntyped<K: Trace>(PhantomData<fn() -> K>);30struct ThunkFromUntyped<K: Trace>(PhantomData<fn() -> K>);
49 }61 }
50}62}
5163
64pub trait ParseTypedObj: Typed {
65 fn parse(obj: &ObjValue) -> Result<Self>;
66}
52pub trait TypedObj: Typed {67pub trait SerializeTypedObj: Typed {
53 fn serialize(self, out: &mut ObjValueBuilder) -> Result<()>;68 fn serialize(self, out: &mut ObjValueBuilder) -> Result<()>;
54 fn parse(obj: &ObjValue) -> Result<Self>;
55 fn into_object(self) -> Result<ObjValue> {69 fn into_object(self) -> Result<ObjValue> {
56 let mut builder = ObjValueBuilder::new();70 let mut builder = ObjValueBuilder::new();
57 self.serialize(&mut builder)?;71 self.serialize(&mut builder)?;
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-macros/src/lib.rs
+++ b/crates/jrsonnet-macros/src/lib.rs
@@ -13,7 +13,7 @@
 	LitStr, Meta, Pat, Path, PathArguments, Result, ReturnType, Token, Type,
 };
 
-use self::typed::derive_typed_inner;
+use self::typed::{derive_from_untyped_inner, derive_into_untyped_inner, derive_typed_inner};
 
 mod names;
 mod typed;
@@ -451,6 +451,24 @@
 		Err(e) => e.to_compile_error().into(),
 	}
 }
+#[proc_macro_derive(IntoUntyped, attributes(typed))]
+pub fn derive_into_untyped(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
+	let input = parse_macro_input!(item as DeriveInput);
+
+	match derive_into_untyped_inner(input) {
+		Ok(v) => v.into(),
+		Err(e) => e.to_compile_error().into(),
+	}
+}
+#[proc_macro_derive(FromUntyped, attributes(typed))]
+pub fn derive_from_untyped(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
+	let input = parse_macro_input!(item as DeriveInput);
+
+	match derive_from_untyped_inner(input) {
+		Ok(v) => v.into(),
+		Err(e) => e.to_compile_error().into(),
+	}
+}
 
 struct FormatInput {
 	formatting: LitStr,
modifiedcrates/jrsonnet-macros/src/typed.rsdiffbeforeafterboth
--- a/crates/jrsonnet-macros/src/typed.rs
+++ b/crates/jrsonnet-macros/src/typed.rs
@@ -301,26 +301,49 @@
 
 	let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
 
-	let capacity = fields.len();
+	let fields = fields
+		.iter()
+		.filter_map(TypedField::expand_field)
+		.collect::<Vec<_>>();
+	Ok(quote! {
+		const _: () = {
+			use ::jrsonnet_evaluator::typed::__typed_macro_prelude::*;
 
-	let typed = {
-		let fields = fields
-			.iter()
-			.filter_map(TypedField::expand_field)
-			.collect::<Vec<_>>();
-		quote! {
 			impl #impl_generics Typed for #ident #ty_generics #where_clause {
 				const TYPE: &'static ComplexValType = &ComplexValType::ObjectRef(&[
 					#(#fields,)*
 				]);
 			}
+		};
+	})
+}
+pub fn derive_into_untyped_inner(input: DeriveInput) -> Result<TokenStream> {
+	let syn::Data::Struct(data) = &input.data else {
+		return Err(Error::new(input.span(), "only structs supported"));
+	};
+
+	let ident = &input.ident;
+	let fields = data
+		.fields
+		.iter()
+		.map(TypedField::parse)
+		.collect::<Result<Vec<_>>>()?;
+
+	let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+
+	let capacity = fields.len();
+
+	let mut names = Names::default();
+
+	let fields_serialize = fields
+		.iter()
+		.map(|f| f.expand_serialize(&mut names))
+		.collect::<Vec<_>>();
 
-			impl #impl_generics FromUntyped for #ident #ty_generics #where_clause {
-				fn from_untyped(value: Val) -> JrResult<Self> {
-					let obj = value.as_obj().expect("shape is correct");
-					Self::parse(&obj)
-				}
-			}
+	let names_expanded = names.expand();
+	Ok(quote! {
+		const _: () = {
+			use ::jrsonnet_evaluator::typed::__typed_macro_prelude::*;
 
 			impl #impl_generics IntoUntyped for #ident #ty_generics #where_clause {
 				fn into_untyped(value: Self) -> JrResult<Val> {
@@ -329,42 +352,57 @@
 					Ok(Val::Obj(out.build()))
 				}
 			}
-		}
+
+			#names_expanded
+
+			impl #impl_generics SerializeTypedObj for #ident #ty_generics #where_clause {
+				fn serialize(self, out: &mut ObjValueBuilder) -> JrResult<()> {
+					NAMES.with(|__names| {
+						#(#fields_serialize)*
+
+						Ok(())
+					})
+				}
+			}
+		};
+	})
+}
+pub fn derive_from_untyped_inner(input: DeriveInput) -> Result<TokenStream> {
+	let syn::Data::Struct(data) = &input.data else {
+		return Err(Error::new(input.span(), "only structs supported"));
 	};
 
+	let ident = &input.ident;
+	let fields = data
+		.fields
+		.iter()
+		.map(TypedField::parse)
+		.collect::<Result<Vec<_>>>()?;
+
+	let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+
 	let mut names = Names::default();
 
 	let fields_parse = fields
 		.iter()
 		.map(|f| f.expand_parse(&mut names))
-		.collect::<Vec<_>>();
-	let fields_serialize = fields
-		.iter()
-		.map(|f| f.expand_serialize(&mut names))
 		.collect::<Vec<_>>();
 
 	let names_expanded = names.expand();
 	Ok(quote! {
 		const _: () = {
-			use ::jrsonnet_evaluator::{
-				typed::{ComplexValType, Typed, IntoUntyped, FromUntyped, TypedObj, CheckType},
-				Val, State,
-				error::{ErrorKind, Result as JrResult},
-				ObjValueBuilder, ObjValue, IStr,
-			};
+			use ::jrsonnet_evaluator::typed::__typed_macro_prelude::*;
 
-			#typed
+			impl #impl_generics FromUntyped for #ident #ty_generics #where_clause {
+				fn from_untyped(value: Val) -> JrResult<Self> {
+					let obj = value.as_obj().expect("shape is correct");
+					Self::parse(&obj)
+				}
+			}
 
 			#names_expanded
 
-			impl #impl_generics TypedObj for #ident #ty_generics #where_clause {
-				fn serialize(self, out: &mut ObjValueBuilder) -> JrResult<()> {
-					NAMES.with(|__names| {
-						#(#fields_serialize)*
-
-						Ok(())
-					})
-				}
+			impl #impl_generics ParseTypedObj for #ident #ty_generics #where_clause {
 				fn parse(obj: &ObjValue) -> JrResult<Self> {
 					NAMES.with(|__names| Ok(Self {
 						#(#fields_parse)*
modifiedcrates/jrsonnet-stdlib/src/manifest/ini.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/manifest/ini.rs
+++ b/crates/jrsonnet-stdlib/src/manifest/ini.rs
@@ -82,7 +82,7 @@
 	Ok(())
 }
 
-#[derive(Typed)]
+#[derive(Typed, FromUntyped)]
 struct IniObj {
 	main: Option<ObjValue>,
 	// TODO: Preserve section order?