Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# nameof

nameof
======
[![Crate Version](https://img.shields.io/crates/v/nameof.svg)](https://crates.io/crates/nameof)
[![Build Status](https://travis-ci.org/SilentByte/nameof.svg?branch=master)](https://travis-ci.org/SilentByte/nameof)
[![MIT License](https://img.shields.io/badge/license-MIT%20License-blue.svg)](https://opensource.org/licenses/MIT)

The `name_of!()` macro defined in this crate takes a binding, type, const, or function as an argument and returns its unqualified string representation. If the identifier does not exist in the current context, the macro will cause a compilation error. This macro is mainly intended for debugging purposes and to improve the refactoring experience compared to `stringify!()`.

The `name_of!()` macro defined in this crate takes a binding, type, const,
function, or enum variant as an argument and returns its unqualified string
representation. If the identifier does not exist in the current context, the
macro will cause a compilation error. This macro is mainly intended for
debugging purposes and to improve the refactoring experience compared to
`stringify!()`.

## Usage

Expand All @@ -28,7 +31,6 @@ fn main() {
}
```


## Examples

The `name_of!()` macro is used as follows:
Expand All @@ -48,6 +50,13 @@ struct GenericStruct<T> {
test_field_t: T,
}

#[derive(Debug)]
enum Color {
Red,
Rgb(u8, u8, u8),
Hsl { h: u16, s: u8, l: u8 },
}

fn greet() -> &'static str {
"Hi, World"
}
Expand Down Expand Up @@ -82,6 +91,12 @@ fn main() {
name_of!(type i32),
name_of!(type f64)
);

// Enum variants
println!("Unit variant: {}", name_of!(Color::Red)); // "Red"
println!("Tuple variant: {}", name_of!(Color::Rgb(..))); // "Rgb"
println!("Tuple variant with values: {}", name_of!(Color::Rgb(255, 128, 0))); // "Rgb(255, 128, 0)"
println!("Struct variant: {}", name_of!(Color::Hsl { .. })); // "Hsl"
}
```

Expand Down
164 changes: 164 additions & 0 deletions examples/name_of_enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
//! Example demonstrating the usage of name_of! macro with enum variants.

#[macro_use]
extern crate nameof;

#[allow(dead_code)]
#[derive(Debug)]
enum Color {
Red,
Green,
Blue,
Rgb(u8, u8, u8),
Hsl { h: u16, s: u8, l: u8 },
}

#[allow(dead_code)]
#[derive(Debug)]
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}

fn main() {
println!("=== name_of! macro with enum variants ===\n");

println!("Unit variants:");
println!(" {} -> '{}'", "name_of!(Color::Red)", name_of!(Color::Red));
println!(
" {} -> '{}'",
"name_of!(Color::Green)",
name_of!(Color::Green)
);
println!(
" {} -> '{}'",
"name_of!(Message::Quit)",
name_of!(Message::Quit)
);
println!();

println!("Tuple variants with range syntax (..):");
println!(
" {} -> '{}'",
"name_of!(Color::Rgb(..))",
name_of!(Color::Rgb(..))
);
println!(
" {} -> '{}'",
"name_of!(Message::Write(..))",
name_of!(Message::Write(..))
);
println!(
" {} -> '{}'",
"name_of!(Message::ChangeColor(..))",
name_of!(Message::ChangeColor(..))
);
println!();

println!("Tuple variants with specific values:");
println!(
" {} -> '{}'",
"name_of!(Color::Rgb(255, 128, 0))",
name_of!(Color::Rgb(255, 128, 0))
);
println!(
" {} -> '{}'",
"name_of!(Color::Rgb(0, 0, 0))",
name_of!(Color::Rgb(0, 0, 0))
);
println!(
" {} -> '{}'",
"name_of!(Message::Write(\"hello\".to_string()))",
name_of!(Message::Write("hello".to_string()))
);
println!(
" {} -> '{}'",
"name_of!(Message::ChangeColor(255, 255, 255))",
name_of!(Message::ChangeColor(255, 255, 255))
);
println!();

println!("Struct variants:");
println!(
" {} -> '{}'",
"name_of!(Color::Hsl {{ .. }})",
name_of!(Color::Hsl { .. })
);
println!(
" {} -> '{}'",
"name_of!(Message::Move {{ .. }})",
name_of!(Message::Move { .. })
);
println!();

println!("Unit variant:");
println!(" name_of!(Color::Red) -> '{}'", name_of!(Color::Red));
println!();

println!("Range syntax:");
println!(
" name_of!(Color::Rgb(..)) -> '{}'",
name_of!(Color::Rgb(..))
);

println!();

println!("Specific values:");
println!(
" name_of!(Color::Rgb(255, 0, 128)) -> '{}'",
name_of!(Color::Rgb(255, 0, 128))
);

println!();

let colors = vec![
Color::Red,
Color::Rgb(255, 128, 0),
Color::Hsl {
h: 240,
s: 100,
l: 50,
},
];

for color in &colors {
match color {
Color::Red => println!(" Processing: {} -> {:?}", name_of!(Color::Red), color),
Color::Green => println!(" Processing: {} -> {:?}", name_of!(Color::Green), color),
Color::Blue => println!(" Processing: {} -> {:?}", name_of!(Color::Blue), color),
Color::Rgb(r, g, b) => println!(
" Processing: {} -> {:?}",
name_of!(Color::Rgb(*r, *g, *b)),
color
),
Color::Hsl { .. } => println!(
" Processing: {} -> {:?}",
name_of!(Color::Hsl { .. }),
color
),
}
}

struct TestStruct {
test_field: i32,
}

impl TestStruct {
const TEST_CONST: i32 = 1;
}

let text = "Hello, World!";

println!("Binding: {}", name_of!(text));
println!("Type: {}", name_of!(type TestStruct));
println!("Field: {}", name_of!(test_field in TestStruct));
println!("Constant: {}", name_of!(const TEST_CONST in TestStruct));

println!("Enum variant: {}", name_of!(Color::Red));
println!(
"Enum variant with values: {}",
name_of!(Color::Rgb(255, 255, 255))
);
}
114 changes: 112 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#![crate_name = "nameof"]
#![no_std]

/// Takes a binding, type, const, or function as an argument and returns its
/// Takes a binding, type, const, function, or enum variant as an argument and returns its
/// unqualified string representation. If the identifier does not exist
/// in the current context, the macro will cause a compilation error.
/// This macro is mainly intended for debugging purposes and to improve
Expand All @@ -25,6 +25,12 @@
/// 3. Fields within structs are referred to with the `in` keyword,
/// e.g. `name_of!(some_field in SomeType)`.
///
/// 4. Enum variants support multiple syntaxes:
/// - Unit variants: `name_of!(EnumName::Variant)` → `"Variant"`
/// - Tuple variants with range: `name_of!(EnumName::Variant(..))` → `"Variant"`
/// - Tuple variants with values: `name_of!(EnumName::Variant(value1, value2))` → `"Variant(value1, value2)"`
/// - Struct variants: `name_of!(EnumName::Variant { .. })` → `"Variant"`
///
///
/// # Examples
///
Expand All @@ -43,6 +49,13 @@
/// test_field_t: T,
/// }
///
/// #[derive(Debug)]
/// enum Color {
/// Red,
/// Rgb(u8, u8, u8),
/// Hsl { h: u16, s: u8, l: u8 },
/// }
///
/// fn greet() -> &'static str {
/// "Hi, World"
/// }
Expand Down Expand Up @@ -77,6 +90,12 @@
/// name_of!(type f64)
/// );
///
/// // Enum variants
/// println!("Unit variant: {}", name_of!(Color::Red)); // "Red"
/// println!("Tuple variant: {}", name_of!(Color::Rgb(..))); // "Rgb"
/// println!("Tuple variant with values: {}", name_of!(Color::Rgb(255, 128, 0))); // "Rgb(255, 128, 0)"
/// println!("Struct variant: {}", name_of!(Color::Hsl { .. })); // "Hsl"
///
/// # }
/// ```
#[macro_export]
Expand Down Expand Up @@ -109,6 +128,51 @@ macro_rules! name_of {
};
stringify!($n)
}};

// Covers Enum Unit Variants
($enum_name:ident :: $variant:ident) => {{
let _ = || {
let _ = $enum_name::$variant;
};
stringify!($variant)
}};

// Covers Enum Tuple Variants with range syntax
($enum_name:ident :: $variant:ident ( .. )) => {{
let _ = || {
// Use pattern matching to verify the variant exists
match None::<$enum_name> {
Some($enum_name::$variant(..)) => {}
_ => {}
}
};
stringify!($variant)
}};

// Covers Enum Tuple Variants with specific values
($enum_name:ident :: $variant:ident ( $($value:expr),+ )) => {{
let _ = || {
let _ = $enum_name::$variant($($value,)*);
};
{
extern crate std;
let variant_name = stringify!($variant);
let values = std::vec![$(std::format!("{:?}", $value)),+];
std::format!("{}({})", variant_name, values.join(", "))
}
}};

// Covers Enum Struct Variants
($enum_name:ident :: $variant:ident { .. }) => {{
let _ = || {
// Use pattern matching to verify the variant exists
match None::<$enum_name> {
Some($enum_name::$variant { .. }) => {}
_ => {}
}
};
stringify!($variant)
}};
}

/// Takes the name of a type as its sole parameter,
Expand Down Expand Up @@ -147,7 +211,7 @@ extern crate std;
#[cfg(test)]
mod tests {

use std::string::String;
use std::string::{String, ToString};

fn test_fn() {
//
Expand All @@ -170,6 +234,15 @@ mod tests {
test_field_u: U,
}

#[allow(dead_code)]
#[derive(Debug)]
enum TestEnum {
UnitVariant,
TupleVariant(i32),
TupleVariantMultiple(i32, String),
StructVariant { field1: i32, field2: String },
}

#[test]
fn name_of_binding() {
let test_variable = 123;
Expand Down Expand Up @@ -246,4 +319,41 @@ mod tests {
fn name_of_struct_constant() {
assert_eq!(name_of!(const TEST_CONST in TestStruct), "TEST_CONST");
}

// Tests for name_of! macro with enum variants
#[test]
fn name_of_enum_unit_variant() {
assert_eq!(name_of!(TestEnum::UnitVariant), "UnitVariant");
}

#[test]
fn name_of_enum_tuple_variant() {
assert_eq!(name_of!(TestEnum::TupleVariant(..)), "TupleVariant");
}

#[test]
fn name_of_enum_tuple_variant_multiple() {
assert_eq!(
name_of!(TestEnum::TupleVariantMultiple(..)),
"TupleVariantMultiple"
);
}

#[test]
fn name_of_enum_struct_variant() {
assert_eq!(name_of!(TestEnum::StructVariant { .. }), "StructVariant");
}

#[test]
fn name_of_enum_tuple_variant_with_values() {
assert_eq!(name_of!(TestEnum::TupleVariant(42)), "TupleVariant(42)");
}

#[test]
fn name_of_enum_tuple_variant_multiple_with_values() {
assert_eq!(
name_of!(TestEnum::TupleVariantMultiple(42, "test".to_string())),
"TupleVariantMultiple(42, \"test\")"
);
}
}