Giter Site home page Giter Site logo

kinded's Introduction

Kinded

Nutype Build Status Nutype Documentation

Generate Rust enum variants without associated data

Get Started

use kinded::Kinded;

#[derive(Kinded)]
enum Drink {
    Mate,
    Coffee(String),
    Tea { variety: String, caffeine: bool }
}

let drink = Drink::Coffee("Espresso".to_owned());
assert_eq!(drink.kind(), DrinkKind::Coffee);

Note, the definition of DrinkKind enum is generated automatically as well as Drink::kind() method. To put it simply you get something similar to the following:

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum DrinkKind {
    Mate,
    Coffee,
    Tea
}

impl Drink {
    fn kind(&self) -> DrinkKind {
        Drink::Mate => DrinkKind::Mate,
        Drink::Coffee(..) => DrinkKind::Coffee,
        Drink::Tea { .. } => DrinkKind::Tea,
    }
}

Kinded trait

The library provides Kinded trait:

pub trait Kinded {
    type Kind: PartialEq + Eq + Debug + Clone + Copy;

    fn kind(&self) -> Self::Kind;
}

From the example above, the derived implementation of Kinded for Drink resembles the following:

impl Kinded for Drink {
    type Kind = DrinkKind;

    fn kind(&self) -> DrinkKind { /* implementation */ }
}

The Kinded trait allows to build abstract functions that can be used with different enum types.

Get all kind variants

The kind type gets implementation of ::all() associated function, which returns a vector with all kind variants:

assert_eq!(DrinkKind::all(), [DrinkKind::Mate, DrinkKind::Coffee, DrinkKind::Tea]);

Attributes

Custom kind type name

By default the kind type name is generated by adding postfix Kind to the original enum name. This can be customized with kind = attribute:

use kinded::Kinded;

#[derive(Kinded)]
#[kinded(kind = SimpleDrink)]
enum Drink {
    Mate,
    Coffee(String),
    Tea { variety: String, caffeine: bool }
}

Derive traits

By default the kind type implements the following traits: Debug, Clone, Copy, PartialEq, Eq, Display, FromStr, From<T>, From<&T>.

Extra traits can be derived with derive(..) attribute:

use kinded::Kinded;
use std::collections::HashSet;

#[derive(Kinded)]
#[kinded(derive(Hash))]
enum Drink {
    Mate,
    Coffee(String),
    Tea { variety: String, caffeine: bool }
}

let mut drink_kinds = HashSet::new();
drink_kinds.insert(DrinkKind::Mate);

Display trait

Implementation of Display trait can be customized in the serde fashion:

use kinded::Kinded;

#[derive(Kinded)]
#[kinded(display = "snake_case")]
enum Drink {
    VeryHotBlackTea,
    Milk { fat: f64 },
}

let tea = DrinkKind::VeryHotBlackTea;
assert_eq!(tea.to_string(), "very_hot_black_tea");

The possible values are "snake_case", "camelCase", "PascalCase", "SCREAMING_SNAKE_CASE", "kebab-case", "SCREAMING-KEBAB-CASE", "Title Case", "lowercase", "UPPERCASE".

FromStr trait

The kind type implements FromStr trait. The implementation tries it's best to parse, checking all the possible cases mentioned above.

use kinded::Kinded;

#[derive(Kinded)]
#[kinded(display = "snake_case")]
enum Drink {
    VeryHotBlackTea,
    Milk { fat: f64 },
}

assert_eq!(
    "VERY_HOT_BLACK_TEA".parse::<DrinkKind>().unwrap(),
    DrinkKind::VeryHotBlackTea
);

assert_eq!(
    "veryhotblacktea".parse::<DrinkKind>().unwrap(),
    DrinkKind::VeryHotBlackTea
);

A note about enum-kinds

There is a very similar crate enum-kinds that does almost the same job.

Here is what makes kinded different:

  • It provides Kinded trait, on top of which users can build abstractions.
  • Generates customizable implementation of Display trait.
  • Generates implementation of FromStr trait.
  • Generates kind() function to extra ergonomics.

A note about the war in Ukraine πŸ‡ΊπŸ‡¦

Today I live in Berlin, I have the luxury to live a physically safe life. But I am Ukrainian. The first 25 years of my life I spent in Kharkiv, the second-largest city in Ukraine, 60km away from the border with russia. Today about a third of my home city is destroyed by russians. My parents, my relatives and my friends had to survive the artillery and air attack, living for over a month in basements.

Some of them have managed to evacuate to EU. Some others are trying to live "normal lifes" in Kharkiv, doing there daily duties. And some are at the front line right now, risking their lives every second to protect the rest.

I encourage you to donate to Charity foundation of Serhiy Prytula. Just pick the project you like and donate. This is one of the best-known foundations, you can watch a little documentary about it. Your contribution to the Ukrainian military force is a contribution to my calmness, so I can spend more time developing the project.

Thank you.

License

MIT Β© Serhii Potapov

kinded's People

Contributors

bryceberger avatar greyblake avatar not-matthias avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

kinded's Issues

Use static array to get all kind variants instead of allocating a vector

Currently :all() returns a vector.
Everytime ::all() is called a vector is allocated.

It should be possible to avoid it:

trait Kinded {
    type Kind: std::fmt::Debug + 'static;
    
    const KINDS: &'static [Self::Kind];
}

impl Kinded for Foo {
    type Kind = FooKind;
    
    const KINDS: &'static [FooKind] = &[FooKind::Bar, FooKind::Baz];
}

See:

Const `.kind()` function

It is currently impossible to use the .kind() function in const contexts.

Since you can't have const fn in traits, you could probably fix this by adding an optional cargo feature or macro attribute that can toggle behavior from using the Kinded trait to just implementing a const fn kind().

`no_std` support

This crate doesn't really have any functionality that depends on std so it would be incredibly useful to enable no_std support.

enum-kinds also supports nostd, so I'll use that in the meantime I guess.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.