Skip to content

Commit fb67963

Browse files
committed
Documentation
1 parent 4d6fcb5 commit fb67963

File tree

1 file changed

+91
-6
lines changed

1 file changed

+91
-6
lines changed

src/lib.rs

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,129 @@
1-
//! The Idea is to parse smth like #[path(value, key=value, key(value))] for arbitrary types really.
2-
//! Parsing works the same way as a function call... meaning any syntax valid ther + the additional
3-
//! key=value. One important thing to keep in mind, is the limitation on values being valid
4-
//! expresions so we can rely on syn for the , splitting :D
5-
1+
//! Basic gist is a struct like this:
2+
//! ```
3+
//! #[derive(Attribute)]
4+
//! #[attribute(ident = "collection")]
5+
//! #[attribute(invalid_field = "Error when an unsupported value is set (e.g. meaning=42")]
6+
//! struct CollectionAttribute {
7+
//! // Options are optional by default (will be set to None if not specified)
8+
//! authority: Option<String>,
9+
//! #[attribute(missing = "Error when the value is not set")]
10+
//! name: String,
11+
//! // Any type implementing default can be flagged as default
12+
//! // This will be set to Vec::default() when not specified
13+
//! #[attribute(default)]
14+
//! #[attribute(expected = "Error when an error occured while parsing")]
15+
//! views: Vec<Type>,
16+
//! }
17+
//! ```
18+
//!
19+
//! Will be able to parse an attribute like this:
20+
//! ```
21+
//! #[collection(authority="Some String", name = r#"Another string"#, views = [Option, ()])]
22+
//! ```
23+
//!
24+
//! Any type that [`ConvertParsed`] is implemented for is supported. These should be the general
25+
//! types that syn supports like [`LitStr`](struct@LitStr) or [`Type`] or that have a direct equivalent in those
26+
//! like [`String`], [`char`] or [`f32`]. A special treatment have [`Vecs`](Vec) which are parsed
27+
//! using [`Array`] with the syntax `[a, b, c]` and [`Options`](Option) that will be [`None`] if
28+
//! not specified and [`Some`] when the value is specified via the attribute. It is not
29+
//! specified via `Some(value)` but as just `value`.
630
use std::fmt::Display;
731

832
use proc_macro2::{Literal, Span};
33+
#[doc(hidden)]
934
pub use r#macro::Attribute;
1035
use syn::{
1136
bracketed, parse::Parse, punctuated::Punctuated, Expr, Lit, LitBool, LitByteStr, LitChar,
1237
LitFloat, LitInt, LitStr, Path, Result, Token, Type, __private::ToTokens,
1338
};
1439

40+
#[deny(missing_docs)]
41+
42+
#[doc(hidden)]
1543
pub mod __private {
1644
pub use proc_macro2;
1745
pub use syn;
1846
}
1947

48+
/// The trait you actually derive on your attribute struct.
49+
///
50+
/// Basic gist is a struct like this:
51+
/// ```
52+
/// #[derive(Attribute)]
53+
/// #[attribute(ident = "collection")]
54+
/// #[attribute(invalid_field = "Error when an unsupported value is set (e.g. meaning=42")]
55+
/// struct CollectionAttribute {
56+
/// // Options are optional by default (will be set to None if not specified)
57+
/// authority: Option<String>,
58+
/// #[attribute(missing = "Error when the value is not set")]
59+
/// name: String,
60+
/// // Any type implementing default can be flagged as default
61+
/// // This will be set to Vec::default() when not specified
62+
/// #[attribute(default)]
63+
/// #[attribute(expected = "Error when an error occured while parsing")]
64+
/// views: Vec<Type>,
65+
/// }
66+
/// ```
67+
///
68+
/// Will be able to parse an attribute like this:
69+
/// ```
70+
/// #[collection(authority="Some String", name = r#"Another string"#, views = [Option, ()])]
71+
/// ```
2072
pub trait Attribute
2173
where
2274
Self: Sized,
2375
{
76+
/// Parses an [`IntoIterator`] of [`syn::Attributes`](syn::Attribute) e.g.
77+
/// [`Vec<Attribute>`](Vec).
78+
///
79+
/// It can therefore parse fields set over multiple attributes like:
80+
/// ```
81+
/// #[collection(authority = "Authority", name = "Name")]
82+
/// #[collection(views = [A, B])]
83+
/// ```
84+
/// and also catch duplicate/conflicting settings over those.
85+
///
86+
/// Fails with a [`syn::Error`] so you can conveniently return that as a compiler error in a proc
87+
/// macro.
2488
fn from_attributes(attrs: impl IntoIterator<Item = syn::Attribute>) -> Result<Self>;
2589
}
2690

91+
/// Helper trait to convert syn types implementing [`Parse`] like [`LitStr`](struct@LitStr) to rust
92+
/// types like [`String`]
93+
///
94+
/// You probably don't need to implement this trait, as most syn types like [`LitStr`](struct@LitStr)
95+
/// and [`Type`] or that have a direct equivalent in those like [`String`], [`char`] or [`f32`] are
96+
/// already implemented. A special treatment have [`Vecs`](Vec) which are parsed
97+
/// using the helper [`Array`] with the syntax `[a, b, c]` and [`Options`](Option) that will be
98+
/// [`None`] if not specified and [`Some`] when the value is specified via the attribute. It is not
99+
/// specified via `Some(value)` but as just `value`.
27100
pub trait ConvertParsed
28101
where
29102
Self: Sized,
30103
Self::Type: Error,
31104
{
105+
/// The type this can be converted from
32106
type Type;
107+
/// This takes [`Self::Type`] and converts it to [`Self`].
108+
///
109+
/// This can return an error, e.g. when parsing an integer too large for a [`u8`] into an `u8`
33110
fn convert(value: Self::Type) -> Result<Self>;
111+
/// Should values of this type return their default when they are not specified even when the
112+
/// `default` flag is not specified (only returns `true` for [`Option`] currently)
34113
fn default_by_default() -> bool {
35114
false
36115
}
116+
/// The default value, this is necessary to implement the implicit default behavior of
117+
/// [`Option`]
37118
fn default() -> Self {
38119
unreachable!("default_by_default should only return true if this is overridden")
39120
}
40121
}
41122

42123
/// Helper trait to generate sensible errors
43124
pub trait Error {
125+
/// This is used to be able to create errors more easily. Mostly used through the
126+
/// implementation for [`T: ToTokens`](ToTokens).
44127
fn error(&self, message: impl Display) -> syn::Error;
45128
}
46129

@@ -53,6 +136,7 @@ where
53136
}
54137
}
55138

139+
/// Macro to easily implement [`ConvertParsed`] for syn types
56140
macro_rules! convert_parsed {
57141
($type:path) => {
58142
impl ConvertParsed for $type {
@@ -130,7 +214,8 @@ where
130214
}
131215
}
132216

133-
/// Helper struct to parse array literals
217+
/// Helper struct to parse array literals:
218+
/// `[a, b, c]`
134219
pub struct Array<T> {
135220
data: Vec<T>,
136221
span: Span,

0 commit comments

Comments
 (0)