#[macro_export]
macro_rules! value {
($($value:tt)+) => {
$crate::value_impl!($($value)+)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! value_impl {
(@seq [$($elems:expr,)*] ()) => {
$crate::__private::vec![$($elems,)*]
};
(@seq [$($elems:expr),*] ()) => {
$crate::__private::vec![$($elems),*]
};
(@seq [$($elems:expr,)*] ([ $($val:tt)* ] $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!([$($val)*]),] ($($rest)*))
};
(@seq [$($elems:expr,)*] (#{ $($val:tt)* } $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!(#{$($val)*}),] ($($rest)*))
};
(@seq [$($elems:expr,)*] ({ $($val:tt)* } $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!({$($val)*}),] ($($rest)*))
};
(@seq [$($elems:expr,)*] ($name:ident { $($val:tt)* } $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!($name {$($val)*}),] ($($rest)*))
};
(@seq [$($elems:expr,)*] ($name:ident ( $($val:tt)* ) $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!($name ($($val)*)),] ($($rest)*))
};
(@seq [$($elems:expr,)*] ($name:ident :: $variant:ident { $($val:tt)* } $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!($name :: $variant {$($val)*}),] ($($rest)*))
};
(@seq [$($elems:expr,)*] ($name:ident :: $variant:ident ( $($val:tt)* ) $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!($name :: $variant ($($val)*)),] ($($rest)*))
};
(@seq [$($elems:expr,)*] ($name:ident :: $variant:ident $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!($name :: $variant),] ($($rest)*))
};
(@seq [$($elems:expr,)*] ($next:expr , $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!($next),] ($($rest)*))
};
(@seq [$($elems:expr,)*] ($last:expr)) => {
$crate::value_impl!(@seq [$($elems,)* $crate::value_impl!($last),] ())
};
(@seq [$($elems:expr,)*] (, $($rest:tt)*)) => {
$crate::value_impl!(@seq [$($elems,)*] ($($rest)*))
};
(@fields [$($fields:expr,)*] ()) => {
$crate::__private::vec![$($fields,)*]
};
(@fields [$($fields:expr),*] ()) => {
$crate::__private::vec![$($fields),*]
};
(@fields [$($fields:expr,)*] ($key:ident : [ $($val:tt)* ] $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!([$($val)*]),
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : #{ $($val:tt)* } $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!(#{$($val)*}),
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : $name:ident { $($val:tt)* } $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!($name { $($val)* }),
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : { $($val:tt)* } $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!({$($val)*}),
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : $name:ident ( $($val:tt)* ) $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!($name ($($val)*)),
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : $name:ident :: $variant:ident { $($val:tt)* } $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!($name :: $variant {$($val)*}),
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : $name:ident :: $variant:ident ( $($val:tt)* ) $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!($name :: $variant ($($val)*)),
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : $name:ident :: $variant:ident $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!($name :: $variant),
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : $val:expr , $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!($val)
},
] ($($rest)*))
};
(@fields [$($fields:expr,)*] ($key:ident : $val:expr)) => {
$crate::value_impl!(@fields [$($fields,)*
$crate::recursive_comparison::value::Field {
name: stringify!($key).into(),
value: $crate::value_impl!($val),
},
] ())
};
(@fields [$($fields:expr,)*] (, $($rest:tt)*)) => {
$crate::value_impl!(@fields [$($fields,)*] ($($rest)*))
};
(@map [$($pairs:expr,)*] () ()) => {
$crate::__private::vec![$($pairs,)*]
};
(@map [$($pairs:expr,)*] ($($key:tt)+) (=> $($rest:tt)*)) => {
$crate::value_impl!(@map_val [$($pairs,)*] ($($key)+) () ($($rest)*))
};
(@map [$($pairs:expr,)*] ($($key:tt)*) ($next:tt $($rest:tt)*)) => {
$crate::value_impl!(@map [$($pairs,)*] ($($key)* $next) ($($rest)*))
};
(@map_val [$($pairs:expr,)*] ($($key:tt)+) ($($val:tt)+) (, $($rest:tt)*)) => {
$crate::value_impl!(@map [$($pairs,)* ($crate::value_impl!($($key)+), $crate::value_impl!($($val)+)),] () ($($rest)*))
};
(@map_val [$($pairs:expr,)*] ($($key:tt)+) ($($val:tt)+) ()) => {
$crate::value_impl!(@map [$($pairs,)* ($crate::value_impl!($($key)+), $crate::value_impl!($($val)+)),] () ())
};
(@map_val [$($pairs:expr,)*] ($($key:tt)+) ($($val:tt)*) ($next:tt $($rest:tt)*)) => {
$crate::value_impl!(@map_val [$($pairs,)*] ($($key)+) ($($val)* $next) ($($rest)*))
};
(false) => {
$crate::recursive_comparison::value::Value::Bool(false)
};
(true) => {
$crate::recursive_comparison::value::Value::Bool(true)
};
([ ]) => {
$crate::recursive_comparison::value::Value::Seq($crate::__private::vec![])
};
([ $($tt:tt)+ ]) => {
$crate::recursive_comparison::value::Value::Seq($crate::value_impl!(@seq [] ($($tt)+)))
};
($name:ident { }) => {
$crate::recursive_comparison::value::Value::Struct {
type_name: stringify!($name).into(),
fields: $crate::__private::vec![],
}
};
($name:ident { $($tt:tt)+ }) => {
$crate::recursive_comparison::value::Value::Struct {
type_name: stringify!($name).into(),
fields: $crate::value_impl!(@fields [] ($($tt)+)),
}
};
({ }) => {
$crate::recursive_comparison::value::Value::Struct {
type_name: "".into(),
fields: $crate::__private::vec![],
}
};
({ $($tt:tt)+ }) => {
$crate::recursive_comparison::value::Value::Struct {
type_name: "".into(),
fields: $crate::value_impl!(@fields [] ($($tt)+)),
}
};
($name:ident :: $variant:ident { }) => {
$crate::recursive_comparison::value::Value::StructVariant {
type_name: stringify!($name).into(),
variant: stringify!($variant).into(),
fields: $crate::__private::vec![],
}
};
($name:ident :: $variant:ident { $($tt:tt)+ }) => {
$crate::recursive_comparison::value::Value::StructVariant {
type_name: stringify!($name).into(),
variant: stringify!($variant).into(),
fields: $crate::value_impl!(@fields [] ($($tt)+)),
}
};
($name:ident :: $variant:ident ( $($tt:tt)+ )) => {
$crate::recursive_comparison::value::tuple_variant(
stringify!($name),
stringify!($variant),
$crate::value_impl!(@seq [] ($($tt)+))
)
};
($name:ident :: $variant:ident) => {
$crate::recursive_comparison::value::Value::UnitVariant {
type_name: stringify!($name).into(),
variant: stringify!($variant).into(),
}
};
($name:ident ( )) => {
$crate::recursive_comparison::value::Value::Struct {
type_name: stringify!($name).into(),
fields: $crate::__private::vec![],
}
};
($name:ident ( $($tt:tt)+ )) => {
$crate::recursive_comparison::value::tuple_struct(
stringify!($name),
$crate::value_impl!(@seq [] ($($tt)+))
)
};
(#{ }) => {
$crate::recursive_comparison::value::Value::Map(
$crate::recursive_comparison::value::Map::new()
)
};
(#{ $($tt:tt)+ }) => {
$crate::recursive_comparison::value::Value::Map(
$crate::recursive_comparison::value::Map::from_iter(
$crate::value_impl!(@map [] () ($($tt)+))
)
)
};
($name:ident) => {
$crate::recursive_comparison::value::Value::Struct {
type_name: stringify!($name).into(),
fields: $crate::__private::vec![],
}
};
(()) => {
$crate::recursive_comparison::value::Value::Unit
};
(( $($tt:tt)+ )) => {
$crate::recursive_comparison::value::tuple($crate::value_impl!(@seq [] ($($tt)+)))
};
($val:expr) => {
$crate::recursive_comparison::serialize::to_recursive_value(&$val)
.unwrap_or_else(|err| panic!("failed to serialize expression: {err}"))
};
}
#[cfg(test)]
mod tests;