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

difftreelog

source

crates/nix-eval/src/macros.rs4.7 KiBsourcehistory
1use serde::Serialize;23use crate::{NixSession, Value};45#[derive(Clone)]6pub struct NixExprBuilder {7	pub(crate) out: String,8	used_fields: Vec<Value>,9}10impl NixExprBuilder {11	pub fn object() -> Self {12		NixExprBuilder {13			out: "{ ".to_owned(),14			used_fields: Vec::new(),15		}16	}17	pub fn string(s: &str) -> Self {18		NixExprBuilder {19			out: nixlike::serialize(s)20				.expect("no problems with serializing_string")21				.trim_end()22				.to_owned(),23			used_fields: Vec::new(),24		}25	}26	pub fn serialized(v: impl Serialize) -> Self {27		let serialized = nixlike::serialize(v).expect("invalid value for apply");28		Self {29			out: serialized.trim_end().to_owned(),30			used_fields: Vec::new(),31		}32	}33	pub fn value(f: Value) -> Self {34		Self {35			out: format!("sess_field_{}", f.session_field_id()),36			used_fields: vec![f],37		}38	}39	pub fn end_obj(&mut self) {40		self.out.push('}');41	}42	pub fn obj_key(&mut self, name: Self, value: Self) {43		self.out.push_str(r#""${"#);44		self.extend(name);45		self.out.push_str(r#"}" = "#);46		self.extend(value);47		self.out.push_str("; ");48	}4950	pub fn extend(&mut self, e: Self) {51		self.out.push_str(&e.out);52		self.used_fields.extend(e.used_fields);53	}5455	#[allow(dead_code)]56	pub fn session(&self) -> NixSession {57		let mut session = None;58		for ele in &self.used_fields {59			if session.is_none() {60				session = Some(ele.session());61				continue;62			}63			let session = session.as_ref().expect("checked");64			let ele_sess = ele.session();65			assert!(66				NixSession::ptr_eq(session, &ele_sess),67				"can't mix fields from different session"68			);69		}70		session.expect("expr without fields used")71	}72	#[allow(dead_code)]73	pub fn index_attr(&mut self, s: &str) {74		let escaped = nixlike::serialize(s).expect("string");75		self.out.push('.');76		self.out.push_str(escaped.trim_end());77	}78}7980#[macro_export]81macro_rules! nix_expr_inner {82	//(@munch_object FIXME: value should be arbitrary nix_expr_inner input... Time to write proc-macro?83	(@obj($o:ident) $field:ident, $($tt:tt)*) => {{84		$o.obj_key(85			NixExprBuilder::string(stringify!($field)),86			NixExprBuilder::value($field),87		);88		nix_expr_inner!(@obj($o) $($tt)*);89	}};90	(@obj($o:ident) $field:ident: $v:block, $($tt:tt)*) => {{91		$o.obj_key(92			NixExprBuilder::string(stringify!($field)),93			NixExprBuilder::serialized(&$v),94		);95		nix_expr_inner!(@obj($o) $($tt)*);96	}};97	(@obj($o:ident)) => {{}};98	(Obj { $($tt:tt)* }) => {{99		use $crate::{macros::NixExprBuilder, nix_expr_inner};100		let mut out = NixExprBuilder::object();101		nix_expr_inner!(@obj(out) $($tt)*);102		out.end_obj();103		out104	}};105	(@field($o:ident) . $var:ident $($tt:tt)*) => {{106		$o.index_attr(stringify!($var));107		nix_expr_inner!(@field($o) $($tt)*);108	}};109	(@field($o:ident) [{ $v:expr }] $($tt:tt)*) => {{110		$o.push(Index::attr(&$v));111		nix_expr_inner!(@o($o) $($tt)*);112	}};113	(@field($o:ident) [ $($var:tt)+ ] $($tt:tt)*) => {{114		$o.push(Index::Expr($crate::nix_expr_inner!($($var)+)));115		nix_expr_inner!(@o($o) $($tt)*);116	}};117	(@field($o:ident) ($($var:tt)*) $($tt:tt)*) => {118		$o.push(Index::ExprApply($crate::nix_expr_inner!($($var)+)));119		nix_expr_inner!(@o($o) $($tt)*);120	};121	(@field($o:ident)) => {};122	($field:ident $($tt:tt)*) => {{123		use $crate::{macros::NixExprBuilder, nix_expr_inner};124		// might be used if indexed125		#[allow(unused_mut)]126		let mut out = NixExprBuilder::value($field.clone());127		nix_expr_inner!(@field(out) $($tt)*);128		out129	}};130	($v:literal) => {{131		use $crate::macros::NixExprBuilder;132		NixExprBuilder::string($v)133	}};134	({$v:expr}) => {{135		use $crate::macros::NixExprBuilder;136		NixExprBuilder::serialized(&$v)137	}}138}139#[macro_export]140macro_rules! nix_expr {141	($($tt:tt)+) => {{142		use $crate::{macros::{NixExprBuilder}, Value, nix_expr_inner};143		let expr = nix_expr_inner!($($tt)+);144		Field::new(expr.session(), expr.out)145	}};146}147148#[macro_export]149macro_rules! nix_go {150	(@o($o:ident) . $var:ident $($tt:tt)*) => {{151		$o.push(Index::attr(stringify!($var)));152		nix_go!(@o($o) $($tt)*);153	}};154	(@o($o:ident) [{ $v:expr }] $($tt:tt)*) => {{155		$o.push(Index::attr(&$v));156		nix_go!(@o($o) $($tt)*);157	}};158	(@o($o:ident) [ $($var:tt)+ ] $($tt:tt)*) => {{159		$o.push(Index::Expr($crate::nix_expr_inner!($($var)+)));160		nix_go!(@o($o) $($tt)*);161	}};162	(@o($o:ident) ($($var:tt)*) $($tt:tt)*) => {163		$o.push(Index::ExprApply($crate::nix_expr_inner!($($var)+)));164		nix_go!(@o($o) $($tt)*);165	};166	(@o($o:ident) | $($var:tt)*) => {167		$o.push(Index::Pipe($crate::nix_expr_inner!($($var)+)));168	};169	(@o($o:ident)) => {};170	($field:ident $($tt:tt)+) => {{171		use $crate::{nix_go, Index};172		let field = $field.clone();173		let mut out = vec![];174		nix_go!(@o(out) $($tt)*);175		field.select(out).await?176	}}177}178#[macro_export]179macro_rules! nix_go_json {180	($($tt:tt)*) => {{181		$crate::nix_go!($($tt)*).as_json().await?182	}};183}