Skip to content

Commit 507ef7c

Browse files
committed
chore: introduction to abuse of structfields
1 parent 8a1af4a commit 507ef7c

File tree

8 files changed

+202
-16
lines changed

8 files changed

+202
-16
lines changed

.github/workflows/release.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Cargo CI
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
workflow_dispatch:
8+
9+
jobs:
10+
publish:
11+
name: Publish
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout sources
15+
uses: actions/checkout@v2
16+
17+
- name: Install stable toolchain
18+
uses: actions-rs/toolchain@v1
19+
with:
20+
profile: minimal
21+
toolchain: stable
22+
override: true
23+
24+
- run: cargo publish --token ${CRATES_TOKEN}
25+
env:
26+
CRATES_TOKEN: ${{ secrets.CRATES_TOKEN }}

Cargo.lock

Lines changed: 58 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
[package]
2-
name = "template"
2+
name = "maydon"
33
version = "0.1.0"
44
edition = "2021"
5-
homepage = "https://github.com/xinux-org/templates"
6-
repository = "https://github.com/xinux-org/templates"
7-
description = "Just a Rust template via nix flakes"
5+
homepage = "https://github.com/rust-lang-uz/maydon"
6+
repository = "https://github.com/rust-lang-uz/maydon"
7+
description = "Generating enumation for fields of a struct"
8+
authors = ["Sokhibjon Orzikulov <orzklv.uz>"]
9+
keywords = ["fields", "enum"]
10+
license = "MIT OR Apache-2.0"
11+
12+
[lib]
13+
proc-macro = true
814

915
# Dependencies that will included with final binary
1016
[dependencies]
17+
syn = { version = "2.0", features = ["derive", "full"] }
18+
quote = "1.0"
19+
proc-macro2 = "1.0"
20+
convert_case = "0.7.1"
1121

1222
# Development dependencies which aren't used in release binary
1323
[dev-dependencies]
14-
15-
# Optimize release binary as much as possible
16-
[profile.release]
17-
strip = true
18-
opt-level = "z"
19-
lto = true
20-
codegen-units = 1
24+
# trybuild = "1.0.103"

src/lib.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#![allow(clippy::useless_conversion)]
2+
3+
use convert_case::{Case, Casing};
4+
use proc_macro::TokenStream;
5+
use quote::quote;
6+
use syn::{parse_macro_input, DeriveInput, Expr, Lit, Meta};
7+
8+
#[proc_macro_derive(Maydon, attributes(name))]
9+
pub fn field_enum_derive(input: TokenStream) -> TokenStream {
10+
let input = parse_macro_input!(input as DeriveInput);
11+
12+
// Default enum name
13+
let mut enum_name = syn::Ident::new("Field", proc_macro2::Span::call_site());
14+
15+
// Parse attributes to extract custom enum name
16+
for attr in input.attrs.iter() {
17+
if attr.path().is_ident("name") {
18+
if let Ok(Meta::NameValue(name_value)) = attr.meta.clone().try_into() {
19+
// Extract value from Meta::NameValue
20+
if let Expr::Lit(expr_lit) = name_value.value {
21+
if let Lit::Str(lit_str) = expr_lit.lit {
22+
enum_name =
23+
syn::Ident::new(&lit_str.value(), proc_macro2::Span::call_site());
24+
}
25+
}
26+
}
27+
}
28+
}
29+
30+
// Extract fields from the struct
31+
let fields = if let syn::Data::Struct(data_struct) = &input.data {
32+
&data_struct.fields
33+
} else {
34+
panic!("FieldEnum can only be derived for structs");
35+
};
36+
37+
let field_variants = fields.iter().map(|field| {
38+
let field_name = &field.ident;
39+
let variant_name = syn::Ident::new(
40+
&field_name
41+
.as_ref()
42+
.unwrap()
43+
.to_string()
44+
.to_case(Case::Pascal),
45+
proc_macro2::Span::call_site(),
46+
);
47+
quote! { #variant_name }
48+
});
49+
50+
let expanded = quote! {
51+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52+
pub enum #enum_name {
53+
#(#field_variants,)*
54+
Unknown,
55+
}
56+
};
57+
58+
TokenStream::from(expanded)
59+
}

src/main.rs

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/basic.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use maydon::Maydon;
2+
3+
#[derive(Maydon)]
4+
pub struct Config {
5+
pub url: String,
6+
pub port: u16,
7+
pub database_url: String,
8+
pub threads: u16,
9+
}
10+
11+
// The macro should generate:
12+
fn main() {
13+
let _ = Field::Url;
14+
let _ = Field::Port;
15+
let _ = Field::DatabaseUrl;
16+
let _ = Field::Threads;
17+
let _ = Field::Unknown;
18+
}

tests/custom.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use maydon::Maydon;
2+
3+
#[derive(Maydon)]
4+
#[name = "ConfigField"]
5+
pub struct Config {
6+
pub url: String,
7+
pub port: u16,
8+
}
9+
10+
// The macro should generate:
11+
fn main() {
12+
let _ = ConfigField::Url;
13+
let _ = ConfigField::Port;
14+
let _ = ConfigField::Unknown;
15+
}

tests/fail.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use maydon::Maydon;
2+
3+
#[derive(Maydon)]
4+
enum InvalidEnum {
5+
// ❌ Macros should only be used on structs
6+
A,
7+
B,
8+
C,
9+
}
10+
11+
fn main() {}

0 commit comments

Comments
 (0)