mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-17 04:48:21 +00:00
Add new CompareFields trait and derive
This commit is contained in:
10
eth2/utils/compare_fields/Cargo.toml
Normal file
10
eth2/utils/compare_fields/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "compare_fields"
|
||||
version = "0.1.0"
|
||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dev-dependencies]
|
||||
compare_fields_derive = { path = "../compare_fields_derive" }
|
||||
|
||||
[dependencies]
|
||||
11
eth2/utils/compare_fields/src/lib.rs
Normal file
11
eth2/utils/compare_fields/src/lib.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct FieldComparison {
|
||||
pub equal: bool,
|
||||
pub field_name: String,
|
||||
pub a: String,
|
||||
pub b: String,
|
||||
}
|
||||
|
||||
pub trait CompareFields {
|
||||
fn compare_fields(&self, b: &Self) -> Vec<FieldComparison>;
|
||||
}
|
||||
46
eth2/utils/compare_fields/tests/tests.rs
Normal file
46
eth2/utils/compare_fields/tests/tests.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use compare_fields::{CompareFields, FieldComparison};
|
||||
use compare_fields_derive::CompareFields;
|
||||
|
||||
#[derive(Clone, Debug, CompareFields)]
|
||||
pub struct Simple {
|
||||
a: u64,
|
||||
b: u16,
|
||||
c: Vec<u8>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compare() {
|
||||
let foo = Simple {
|
||||
a: 42,
|
||||
b: 12,
|
||||
c: vec![1, 2],
|
||||
};
|
||||
|
||||
let mut bar = foo.clone();
|
||||
|
||||
let comparisons = foo.compare_fields(&bar);
|
||||
|
||||
assert!(!comparisons.iter().any(|c| c.equal == false));
|
||||
|
||||
assert_eq!(
|
||||
comparisons[0],
|
||||
FieldComparison {
|
||||
equal: true,
|
||||
field_name: "a".to_string(),
|
||||
a: "42".to_string(),
|
||||
b: "42".to_string(),
|
||||
}
|
||||
);
|
||||
|
||||
bar.a = 30;
|
||||
|
||||
assert_eq!(
|
||||
foo.compare_fields(&bar)[0],
|
||||
FieldComparison {
|
||||
equal: false,
|
||||
field_name: "a".to_string(),
|
||||
a: "42".to_string(),
|
||||
b: "30".to_string(),
|
||||
}
|
||||
);
|
||||
}
|
||||
12
eth2/utils/compare_fields_derive/Cargo.toml
Normal file
12
eth2/utils/compare_fields_derive/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "compare_fields_derive"
|
||||
version = "0.1.0"
|
||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = "0.15"
|
||||
quote = "0.6"
|
||||
58
eth2/utils/compare_fields_derive/src/lib.rs
Normal file
58
eth2/utils/compare_fields_derive/src/lib.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
#![recursion_limit = "256"]
|
||||
extern crate proc_macro;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(CompareFields)]
|
||||
pub fn compare_fields_derive(input: TokenStream) -> TokenStream {
|
||||
let item = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let name = &item.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = &item.generics.split_for_impl();
|
||||
|
||||
let struct_data = match &item.data {
|
||||
syn::Data::Struct(s) => s,
|
||||
_ => panic!("compare_fields_derive only supports structs."),
|
||||
};
|
||||
|
||||
let mut idents_a = vec![];
|
||||
let mut field_names = vec![];
|
||||
|
||||
for field in struct_data.fields.iter() {
|
||||
let ident = match &field.ident {
|
||||
Some(ref ident) => ident,
|
||||
_ => panic!("compare_fields_derive only supports named struct fields."),
|
||||
};
|
||||
|
||||
field_names.push(format!("{:}", ident));
|
||||
idents_a.push(ident);
|
||||
}
|
||||
|
||||
let idents_b = idents_a.clone();
|
||||
let idents_c = idents_a.clone();
|
||||
let idents_d = idents_a.clone();
|
||||
|
||||
let output = quote! {
|
||||
impl #impl_generics compare_fields::CompareFields for #name #ty_generics #where_clause {
|
||||
fn compare_fields(&self, b: &Self) -> Vec<compare_fields::FieldComparison> {
|
||||
let mut comparisons = vec![];
|
||||
|
||||
#(
|
||||
comparisons.push(
|
||||
compare_fields::FieldComparison {
|
||||
equal: self.#idents_a == b.#idents_b,
|
||||
field_name: #field_names.to_string(),
|
||||
a: format!("{:?}", self.#idents_c),
|
||||
b: format!("{:?}", b.#idents_d),
|
||||
}
|
||||
);
|
||||
)*
|
||||
|
||||
comparisons
|
||||
}
|
||||
}
|
||||
};
|
||||
output.into()
|
||||
}
|
||||
Reference in New Issue
Block a user