#macro-derive #compile-time #getter #type #field

get-field-by-type

Get a value of field, based on the type of a field

4 releases

new 0.0.5 Jul 2, 2025
0.0.4 Mar 1, 2024
0.0.3 Sep 15, 2023
0.0.2 Jun 27, 2023

#880 in Rust patterns

Download history 39/week @ 2025-03-13 23/week @ 2025-03-20 13/week @ 2025-03-27 4/week @ 2025-04-03 46/week @ 2025-04-10 101/week @ 2025-04-17 18/week @ 2025-04-24 95/week @ 2025-05-01 41/week @ 2025-05-08 20/week @ 2025-05-15 19/week @ 2025-05-22 8/week @ 2025-06-05 19/week @ 2025-06-12 37/week @ 2025-06-19 72/week @ 2025-06-26

139 downloads per month
Used in 4 crates (via ezno-parser)

MIT license

6KB

Get-field-by-type

crates.io badge docs.rs badge

Create a getter for a field based on its type. For example

use get_field_by_type::GetFieldByType;

#[derive(GetFieldByType)]
#[get_field_by_type_target(i32)]
enum Enum1 {
	A(i32, char),
	B(i32, bool),
	C(i32, String)
}

let x = Enum1::A(12, '!');
assert_eq!(*GetFieldByType::<i32>::get(&x), 12);

Why not impl &Self for Into<&T>

Using Into on references for getting a field is a bit of hack. This is designed for getting the value for a field with a common type. Using a custom trait also means flexibility in the future

Additional options and features

When a struct of variant doesn't have a type, there are two behaviors

Either a compile time error (default)

Or a specified statement to evaluate. This could be a panic

use get_field_by_type::GetFieldByType;

#[derive(GetFieldByType)]
#[get_field_by_type_target(i32)]
#[get_field_no_type_behavior(panic!("could not find item");)]
enum Enum2 {
	A(i32),
	B(i32),
	C
}

assert_eq!(*GetFieldByType::<i32>::get(&Enum2::A(12)), 12);

let result = std::panic::catch_unwind(|| {
	let _value = *GetFieldByType::<i32>::get(&Enum2::C);
});
assert!(result.is_err());

or returning a constant value

use get_field_by_type::GetFieldByType;

#[derive(GetFieldByType)]
#[get_field_by_type_target(i32)]
#[get_field_no_type_behavior(return &0;)]
enum Enum2 {
	A(i32),
	B(i32),
	C
}

assert_eq!(*GetFieldByType::<i32>::get(&Enum2::A(12)), 12);
assert_eq!(*GetFieldByType::<i32>::get(&Enum2::C), 0);

Recursive on unit variants

In the AOrB enum case, the derive macro can't find a i32 on variant AOrB::A. However, as it is a unit variant, the implementation delegates it to the unit type.

use get_field_by_type::GetFieldByType;

#[derive(GetFieldByType)]
#[get_field_by_type_target(i32)]
struct A(pub i32);

#[derive(GetFieldByType)]
#[get_field_by_type_target(i32)]
struct B(pub i32);

#[derive(GetFieldByType)]
#[get_field_by_type_target(i32)]
enum AOrB {
	A(A),
	B(B)
}

let b = B(10);
assert_eq!(*GetFieldByType::<i32>::get(&b), 10);

let a_or_b = AOrB::B(b);
assert_eq!(*GetFieldByType::<i32>::get(&a_or_b), 10);

With support through Box

use get_field_by_type::GetFieldByType;

#[derive(GetFieldByType)]
#[get_field_by_type_target(i32)]
struct A(pub i32);

#[derive(GetFieldByType)]
#[get_field_by_type_target(i32)]
enum JustA {
	A(Box<A>),
}

let a = JustA::A(Box::new(A(10)));
assert_eq!(*GetFieldByType::<i32>::get(&a), 10);

Alternatives

For more manual field access, check out getset. If looking for getting multiple fields, check out getters-by-type

Dependencies

~245–670KB
~16K SLoC