Skip to content

Commit

Permalink
Refactor derive(Config) macro docs
Browse files Browse the repository at this point in the history
Having attributes as bullet points was annoying as some attributes have
long descriptions. Using headings also allows to jump to them and shows
a table of contents.
  • Loading branch information
LukasKalbertodt committed Oct 17, 2024
1 parent d454f09 commit ce3b266
Showing 1 changed file with 82 additions and 55 deletions.
137 changes: 82 additions & 55 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ pub use crate::{

/// Derives (automatically implements) [`Config`] for a struct.
///
/// This only works for structs with named fields, but not for tuple structs,
/// unit structs, enums, or unions. This macro only works sometimes inside of
/// This only works for structs with named fields (i.e. not for tuple structs,
/// unit structs, enums, or unions). This macro only works sometimes inside of
/// functions (as it generates a module and symbol resolution is weird in that
/// case); if you get weird errors "symbol not found", just move the struct
/// definition outside of the function.
Expand Down Expand Up @@ -275,77 +275,104 @@ pub use crate::{
/// stored in [`Meta`][meta::Meta]. They are used in the formatting functions
/// (e.g. `toml::format`).
///
/// ## Special types for leaf fields
///
/// These types give a different meaning/semantic to the field. Please note that
/// due to the limitations of derive macros, the type is checked *literally*.
/// So it won't work if you rename symbols or use full paths.
///
/// - **`Option<T>`**: this marks the field as an optional field. All other
/// fields are non-optional and will raise an error if while loading the
/// configuration, no value has been set for them. Optional fields cannot have
/// a `#[config(default = ...)]` attribute as that would not make sense.
///
///
/// ## Field Attributes
///
/// ## Attributes
/// The following attributes can be attached to struct fields.
///
/// This macro currently recognizes the following attributes for leaf fields:
/// ### `default`
///
/// - **`#[config(default = ...)]`**: sets a default value for this field. This
/// is returned by [`Partial::default_values`] and, in most circumstances,
/// used as a last "layer" to pull values from that have not been set in a
/// layer of higher-priority. Currently, the following expressions are
/// allowed:
/// ```ignore
/// #[config(default = ...)]
/// ```
///
/// - Booleans, e.g. `default = true`
/// - Integers, e.g. `default = 900`
/// - Floats, e.g. `default = 3.14`
/// - Strings, e.g. `default = "fox"`
/// - Arrays, e.g. `default = ["foo", "bar"]`
/// - Key value maps, e.g. `default = { "cat": 3.14, "bear": 9.0 }`
/// Sets a default value for this field. This is returned by
/// [`Partial::default_values`] and, in most circumstances, used as a
/// last "layer" to pull values from that have not been set in a layer of
/// higher-priority. Currently, the following expressions are allowed:
///
/// - Booleans, e.g. `default = true`
/// - Integers, e.g. `default = 900`
/// - Floats, e.g. `default = 3.14`
/// - Strings, e.g. `default = "fox"`
/// - Arrays, e.g. `default = ["foo", "bar"]`
/// - Key value maps, e.g. `default = { "cat": 3.14, "bear": 9.0 }`
///
/// Map keys can be Booleans, integers, floats, and strings. For array and map
/// values, you can use any of the expressions in the list above (i.e. you
/// can nest arrays/maps).
///
/// The field value is deserialized from the specified default value
/// (via `serde::de::IntoDeserializer`). So the expression after `default =`
/// is often not the same Rust type as your field. For example, you can have
/// `#[config(default = "/foo/bar")]` on the field `path: PathBuf`. This
/// works fine as `PathBuf` can be deserialized from a string. (Also see the
/// `IpAddr` field in the example above.)
///
/// If you use an integer or float literal without type suffix, `confique` has
/// to infer the exact type from the type of the field. This should work in
/// most cases (`u8`, `f32`, `Vec<i16>`, `[f64; 3]`, ...), but this type
/// inference is very basic, not even close to what Rust can do. If confique
/// cannot figure out the type, it defaults to `i32` for integers and `f64`
/// for floats (like Rust does). If that causes problems for you, just add a
/// type suffix, e.g. `default = 800u32`.
///
/// ### `env`
///
/// Map keys can be Booleans, integers, floats, and strings. For array and map
/// values, you can use any of the expressions in the list above (i.e. you
/// can nest arrays/maps).
/// ```ignore
/// #[config(env = "KEY")]
/// ```
///
/// The field value is deserialized from the specified default value
/// (via `serde::de::IntoDeserializer`). So the expression after `default =`
/// is often not the same Rust type as your field. For example, you can have
/// `#[config(default = "/foo/bar")]` on the field `path: PathBuf`. This
/// works fine as `PathBuf` can be deserialized from a string. (Also see the
/// `IpAddr` field in the example above.)
/// Assigns an environment variable to this field. In [`Partial::from_env`], the
/// variable is checked and deserialized into the field if present.
///
/// If you use an integer or float literal without type suffix, `confique` has
/// to infer the exact type from the type of the field. This should work in
/// most cases (`u8`, `f32`, `Vec<i16>`, `[f64; 3]`, ...), but this type
/// inference is very basic, not even close to what Rust can do. If confique
/// cannot figure out the type, it defaults to `i32` for integers and `f64`
/// for floats (like Rust does). If that causes problems for you, just add a
/// type suffix, e.g. `default = 800u32`.
/// ### `parse_env`
///
/// - **`#[config(env = "KEY")]`**: assigns an environment variable to this
/// field. In [`Partial::from_env`], the variable is checked and
/// deserialized into the field if present.
/// ```ignore
/// #[config(parse_env = path::to::function)]
/// ```
///
/// - **`#[config(deserialize_with = path::to::function)]`**: like
/// [serde's `deserialize_with` attribute][serde-deser].
/// Function used to parse environment variables. Mostly useful if you need to
/// parse lists or other complex objects from env vars. Function needs
/// signature `fn(&str) -> Result<T, impl std::error::Error>` where `T` is the
/// type of the field. Can only be present if the `env` attribute is present.
/// Also see [`env::parse`].
///
/// - **`#[config(parse_env = path::to::function)]`**: function used to parse
/// environment variables. Mostly useful if you need to parse lists or
/// other complex objects from env vars. Function needs signature
/// `fn(&str) -> Result<T, impl std::error::Error>` where `T` is the type of
/// the field.. Can only be present if the `env` attribute is present. Also
/// see [`env::parse`].
/// #### `deserialize_with`
///
/// There are also the following attributes on the struct itself:
/// ```ignore
/// #[config(deserialize_with = path::to::function)]
/// ```
///
/// - **`#[config(partial_attr(...))]`**: specify attributes that should be
/// attached to the partial struct definition. For example,
/// `#[config(partial_attr(derive(Clone)))]` can be used to make the partial
/// type implement `Clone`.
/// Like [serde's `deserialize_with` attribute][serde-deser].
///
/// [serde-deser]: https://serde.rs/field-attrs.html#deserialize_with
///
/// ## Special types for leaf fields
///
/// These types give a different meaning/semantic to the field. Please note that
/// due to the limitations of derive macros, the type is checked *literally*.
/// So it won't work if you rename symbols or use full paths.
/// ## Struct attributes
///
/// - **`Option<T>`**: this marks the field as an optional field. All other
/// fields are non-optional and will raise an error if while loading the
/// configuration, no value has been set for them. Optional fields cannot have
/// a `#[config(default = ...)]` attribute as that would not make sense.
/// The following attributes can be attached to the struct itself.
///
/// ### `partial_attr`
///
/// ```ignore
/// #[config(partial_attr(...))]
/// ```
///
/// Specify attributes that should be attached to the partial struct definition.
/// For example, `#[config(partial_attr(derive(Clone)))]` can be used to make
/// the partial type implement `Clone`.
///
///
/// # What the macro generates
Expand Down

0 comments on commit ce3b266

Please sign in to comment.