1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//! Derive `core::str::FromStr` and `core::fmt::Display` for enums whose
//! variants serialize to hierarchical, delimiter-separated paths.
//!
//! ```
//! use enum_path::EnumPath;
//!
//! #[derive(EnumPath, Clone, Debug, PartialEq, Eq)]
//! #[enum_path(FromStr, Display, rename_all = "snake_case")]
//! enum Action
//! {
//! Exit,
//! SendMessage(String),
//! SetState(State),
//! }
//!
//! #[derive(EnumPath, Clone, Debug, PartialEq, Eq)]
//! #[enum_path(FromStr, Display)]
//! enum State
//! {
//! Idle,
//! Ready,
//! }
//!
//! let parsed: Action = "set_state.Idle".parse().unwrap();
//! assert_eq!(parsed.to_string(), "set_state.Idle");
//! ```
//!
//! # Enum-level attributes
//!
//! Attached as `#[enum_path(...)]` on the enum definition. Multiple flags
//! may appear in the same attribute, comma-separated.
//!
//! | Attribute | Meaning |
//! |----------------------|--------------------------------------------------------------------|
//! | `FromStr` | Derive `core::str::FromStr` for the enum. |
//! | `Display` | Derive `core::fmt::Display` for the enum. |
//! | `rename_all = "..."` | Apply a case convention to every variant; see [Rename casing](#rename-casing). |
//! | `delimiter = "..."` | Separator between a variant name and its inner type; defaults to `"."`. |
//! | `case_insensitive` | Match variant names with ASCII case-insensitive comparison. |
//! | `error = MyError` | Use a custom error type from generated `FromStr` impls; see [Custom error types](#custom-error-types). |
//! | `crate = path` | Override the runtime crate path when `enum_path` is re-exported. |
//!
//! # Per-variant attributes
//!
//! | Attribute | Meaning |
//! |----------------------|--------------------------------------------------|
//! | `rename = "..."` | Override the serialized name for this variant. |
//!
//! # Variant shape requirements
//!
//! Every variant must be either a unit variant (e.g. `Exit`) or a single-field
//! tuple variant (e.g. `SendMessage(String)`). Multi-field tuple variants
//! and named-field variants are rejected at compile time.
//!
//! The inner type of a single-field tuple variant must implement
//! `core::fmt::Display` when the enum derives `Display`, and
//! `core::str::FromStr` when the enum derives `FromStr`. There is no
//! `Self::Item: FromStr` bound on the generated impl; instead the macro
//! generates a `<T as FromStr>::from_str(rest)` call inline, which
//! produces a type error at the call site if the bound is not satisfied.
//!
//! # Custom error types
//!
//! Pass `#[enum_path(FromStr, error = MyError)]` to override the error
//! type used by the generated `FromStr` impl. The supplied type must
//! implement `core::convert::From<enum_path::Error>` so the macro can
//! construct it from a parse failure:
//!
//! ```
//! use enum_path::EnumPath;
//!
//! #[derive(Debug)]
//! struct MyError(enum_path::Error);
//!
//! impl From<enum_path::Error> for MyError
//! {
//! fn from(e: enum_path::Error) -> Self
//! {
//! Self(e)
//! }
//! }
//!
//! #[derive(EnumPath, Clone, Debug, PartialEq, Eq)]
//! #[enum_path(FromStr, error = MyError)]
//! enum Thing
//! {
//! Foo,
//! }
//! ```
//!
//! The generated `FromStr::Err` type becomes `MyError`; the bound is
//! `MyError: From<enum_path::Error>`. The struct field
//! `Error::expected` always holds the *original* enum's name regardless
//! of any wrapping conversion.
//!
//! # Rename casing
//!
//! `rename_all` accepts the usual serde-style values, but the algorithm
//! is built around ASCII case detection and may diverge from serde for
//! some inputs:
//!
//! - **`"lowercase"`** / **`"UPPERCASE"`** call `str::to_lowercase` /
//! `to_uppercase` on the entire identifier with no word splitting.
//! - **`"snake_case"`**, **`"SCREAMING_SNAKE_CASE"`**, **`"kebab-case"`**,
//! **`"SCREAMING-KEBAB-CASE"`**, **`"PascalCase"`**, **`"camelCase"`**
//! first split the identifier into words by walking ASCII case
//! boundaries and digits, then join the lowercased words with the
//! appropriate separator.
//!
//! Caveats of the word splitter:
//!
//! - Word boundaries are detected per-character via
//! `char::is_lowercase`, `char::is_ascii_digit`, and
//! `char::is_alphanumeric`. Identifiers containing non-ASCII letters
//! are split on uppercase / lowercase transitions of those letters
//! (so `ƑōőƂɑρ` splits as `ƒōő` + `ƃɑρ`).
//! - The splitter treats any non-alphanumeric ASCII character as a word
//! boundary and drops it (`Foo_Bar` -> `["Foo", "Bar"]`).
//! - A digit followed by a non-digit alphabetic character starts a new
//! word (`foo23bar` -> `foo23.bar`), and a non-digit character
//! followed by a digit does not (so `Foo2` -> `["Foo2"]`).
//! - Unicode width casing (e.g. the ligature `ffl`) goes through
//! `char::to_lowercase`/`to_uppercase`, which can produce multiple
//! output characters from one input character.
//!
//! If you need behavior the rules above don't capture, set the variant
//! name explicitly with `#[enum_path(rename = "...")]`.
//!
//! # Uniqueness
//!
//! The macro rejects (at compile time) two variants that resolve to the
//! same serialized name, since `FromStr` would otherwise become
//! order-dependent. It also rejects a serialized name that is a prefix
//! of another serialized name followed by the configured delimiter
//! (e.g. variants named `foo` and `foo.bar` would alias under the
//! default `.` delimiter).
extern crate alloc;
use String;
use fmt;
pub use EnumPath;
/// Error returned by generated `FromStr` implementations.
/// Implementation details used by generated code. Not part of the public API.