Skip to content

Commit

Permalink
actions & enhanced doc
Browse files Browse the repository at this point in the history
  • Loading branch information
dandyvica committed Jan 21, 2024
1 parent bd7fc1d commit 5f8f604
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 22 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ jobs:

steps:
- uses: actions/checkout@v3
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }} && rustup component add clippy
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
- name: Clippy
run: cargo clippy
86 changes: 65 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,86 @@
# enum_from procedural macros
# _enum_from_ procedural macros
Straightforward procedural macros to auto-create implementations of ```Display``` , ```FromStr``` and ```TryFrom<u8/u16/...>``` for enums.

Just add ```#[derive(EnumTryFrom, EnumDisplay)]``` to the enum. From ```TryFrom``` ints, the proc-macro is looking at the ```#[repr()]``` attribute which is mandatory.

Supported repr sizes are ```u8/u16/u32/u64/i8/i16/i32/i64```. For the ```TryFrom``` method, if it fails, it returns the value wrapped as an ```Error``` or the value wrapped in the ```Reserved``` variant..

Example:
Supported repr sizes are ```u8/u16/u32/u64/i8/i16/i32/i64```. For the ```TryFrom``` method, if it fails, it returns the value wrapped as an ```Error``` or the value wrapped in the ```Reserved``` variant if such a variant is existing.

## C-like enums
For pure C-like enums:
```rust
// DNS opcodes
#[derive(Debug, PartialEq, EnumTryFrom, EnumDisplay)]
#[repr(u8)]
pub enum OpCode {
Query = 0, //[RFC1035]
#[derive(Debug, PartialEq, EnumDisplay, EnumFromStr, EnumTryFrom)]
#[repr(u16)]
enum OpCode {
Query = 0, //[RFC1035]
IQuery = 1, // (Inverse Query, OBSOLETE) [RFC3425]
Status = 2, // [RFC1035]
Unassigned = 3,
Notify = 4, // [RFC1996]
Update = 5, // [RFC2136]
DOS = 6, // DNS Stateful Operations (DSO) [RFC8490]

// other values unassigned
Reserved(u8),

}

// from_str
let code = OpCodeReserved::from_str("Unassigned").unwrap();
assert_eq!(code, OpCodeReserved::Unassigned);
let code = OpCode::from_str("Unassigned").unwrap();
assert_eq!(code, OpCode::Unassigned);
let code = OpCode::from_str("foo").unwrap_err();
assert_eq!(code, format!("no variant corresponding to value 'foo'"));

// try_from
let code = OpCode::try_from(6u16).unwrap();
assert_eq!(code, OpCode::DOS);
let code = OpCode::try_from(1000u16).unwrap_err();
assert_eq!(code, 1000);

let code = OpCodeReserved::try_from(6u16).unwrap();
assert_eq!(code, OpCodeReserved::DOS);
// display
let code = OpCode::from_str("Unassigned").unwrap();
assert_eq!(&code.to_string(), "Unassigned");
let code = OpCode::try_from(6u16).unwrap();
assert_eq!(&code.to_string(), "DOS");
```

## For unit having a fallback variant
```rust
#[derive(Debug, Default, PartialEq, EnumDisplay, EnumFromStr, EnumTryFrom)]
#[repr(u16)]
pub enum QClass {
#[default]
IN = 1, // the Internet
CS = 2, // the CSNET class (Obsolete - used only for examples in some obsolete RFCs)
CH = 3, // the CHAOS class
HS = 4, // Hesiod [Dyer 87]
ANY = 255,

#[fallback]
CLASS(u16),
}

// from_str
let code = QClass::from_str("IN").unwrap();
assert_eq!(code, QClass::IN);
let code = QClass::from_str("foo").unwrap_err();
assert_eq!(code, format!("no variant corresponding to value 'foo'"));
let code = QClass::from_str("CLASS1234").unwrap();
assert_eq!(code, QClass::CLASS(1234));
let code = QClass::from_str("CLASSA234").unwrap_err();
assert_eq!(code, format!("no variant corresponding to value 'CLASSA234'"));

// try_from
let code = QClass::try_from(4u16).unwrap();
assert_eq!(code, QClass::HS);
let code = QClass::try_from(1000u16).unwrap();
assert_eq!(code, QClass::CLASS(1000));

let code = OpCodeReserved::try_from(1000).unwrap();
assert_eq!(code, OpCodeReserved::Reserved(1000));
assert_eq!(&code.to_string(), "1000");
// display
let code = QClass::from_str("IN").unwrap();
assert_eq!(&code.to_string(), "IN");
let code = QClass::try_from(2u16).unwrap();
assert_eq!(&code.to_string(), "CS");
let code = QClass::try_from(1000u16).unwrap();
assert_eq!(&code.to_string(), "CLASS1000");
let code = QClass::from_str("CLASS1234").unwrap();
assert_eq!(&code.to_string(), "CLASS1234");
```

This is only possible for unit-only enums. Otherwise, compilation panics.
For other kind of enums, compilation panics.

0 comments on commit 5f8f604

Please sign in to comment.