Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@PoignardAzur
Last active January 30, 2021 20:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PoignardAzur/4795888034e8b40b6b312b1d9da2cf3c to your computer and use it in GitHub Desktop.
Save PoignardAzur/4795888034e8b40b6b312b1d9da2cf3c to your computer and use it in GitHub Desktop.
// Everything from here to the --VARIADICS-- marker is valid Rust code right now:
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=38f72335b11bda33e3d6787176786a82
use std::fmt::{Debug, DebugStruct};
struct StandardDebug;
struct Skip;
struct PlaceHolder(String);
struct CustomFormatter<T>(
fn(field: &T, field_name: &str, f: &mut DebugStruct),
);
trait DebugStructField<DebugFieldType> {
fn debug_struct_field(
&self,
field_name: &str,
additional_data: DebugFieldType,
f: &mut DebugStruct<'_, '_>,
);
}
impl<T: Debug> DebugStructField<StandardDebug> for T {
fn debug_struct_field(
&self,
field_name: &str,
_additional_data: StandardDebug,
f: &mut DebugStruct<'_, '_>,
)
{
f.field(field_name, &self);
}
}
impl<T> DebugStructField<Skip> for T {
fn debug_struct_field(
&self,
_field_name: &str,
_additional_data: Skip,
_f: &mut DebugStruct<'_, '_>,
)
{}
}
impl<T> DebugStructField<PlaceHolder> for T {
fn debug_struct_field(
&self,
field_name: &str,
additional_data: PlaceHolder,
f: &mut DebugStruct<'_, '_>,
)
{
f.field(field_name, &additional_data.0);
}
}
impl<T> DebugStructField<CustomFormatter<T>> for T {
fn debug_struct_field(
&self,
field_name: &str,
additional_data: CustomFormatter<T>,
f: &mut DebugStruct<'_, '_>,
)
{
(additional_data.0)(&self, field_name, f);
}
}
// --VARIADICS--
// Reminder this is an example syntax;
// what's important is the information being treated
// and whether the compiler would have access to that info
#[variadic_derive(
MyDebug,
struct,
field_attr=(DebugStructField; StandardDebug, PlaceHolder, CustomFormatter, Skip),
default_field_attr=StandardDebug,
)]
impl<
const STRUCT_NAME: String,
const ...FIELD_NAMES: String,
const ...FIELD_ATTRIBUTES: Attributes,
...Ts,
...Attributes,
Struct: HasVariadicFields<FieldTypes=...Ts>,
> Debug for Struct
where
...Ts: ...DebugStructField<Attributes>
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let mut f = f.debug_struct(&STRUCT_NAME);
for field, field_name, field_data ...in self.get_fields(), FIELD_NAMES, FIELD_ATTRIBUTES {
field.debug_struct_field(&field_name, &field_data, &mut f);
}
f.finish()
}
}
// TODO - figure out how to adapt the generic bounds of the
// struct being derived
// --EXAMPLE--
#[derive(MyDebug)]
struct FooBar {
foo: u8,
#[PlaceHolder("<SomeUnprintableType>")]
bar: SomeUnprintableType,
#[CustomFormatter(my_fmt)]
truc: SomeComplicatedType,
#[Skip]
_machin: std::marker::PhantomData<SomeStuff>,
}
fn my_fmt(field: &SomeComplicatedType, field_name: &str, f: &mut DebugStruct) {
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment