[]Derive Macro vessels::Kind

#[derive(Kind)]
{
    // Attributes available to this derive:
    #[kind]
}

Generates an implementation of Kind for a struct or enum.

This macro has a number of modes of operation. First, it may be used in a fashion equivalent to the manner of operation of standard library derive macros.

use vessels::Kind;

#[derive(Kind)]
struct Person<T> {
    name: T,
    say_hello: Box<dyn Fn() -> T + Sync + Send>,
}

This will generate an implementation of Kind for the annotated type given an extant implementation of Kind for each field of that type. There is further nuance to this mode of operation, but to explain it is best to first demonstrate the other primary manner of operation.

use vessels::{Kind, kind::using};
use serde::{Serialize, Deserialize}

#[derive(Serialize, Deserialize)]
struct NotKind;

#[derive(Serialize, Deserialize, Kind)]
#[kind(using::Serde)]
struct Person {
    name: String,
    data: NotKind,
}

This will generate an implementation of Kind for the annotated type despite NotKind lacking a valid implementation. The types, provided in vessels::kind::using, that provide AsKind trait implementations, allow for the use of an alternative bijection for structs and enums that implement some certain traits permitting such a thing. To finally attend to the additional mode of operation mentioned earlier, these #[kind()] annotations may be used with the initially discussed syntax.

#[derive(Kind)]
struct Person {
    name: String,
    #[kind(using::Serde)]
    data: NotKind,
}

Annotating a field of a struct or enum with #[kind()], if the type provided in the attribute annotation is a valid AsKind for the type of that field, will cause the overarching derivation to use that type as a wrapper to produce a valid Kind bijection. All of the described behavior also functions for arbitrary generic parameters and when used in enums with both named and unnamed fields.

#[derive(Kind)]
enum Entity<T: Kind> {
    Person {
        name: String,
        #[kind(using::Serde)]
        data: NotKind,
    },
    UnnamedFields(#[kind(using::Serde)] NotKind, T)
}