extruct 0.2.1

Extruct is a proc-macro library that provides tools for listing named struct fields and implementing conversion from a larger struct containing fields with same names.
Documentation
#![deny(missing_docs)]
//! # Extruct
//!
//! Extruct is a proc-macro library that provides tools for listing named struct fields and
//! implementing conversion from a larger struct containing fields with same names.
//!
//! ## Description
//! Extruct is primarily driven by the following use-case.
//! <br>
//! It is customary for REST API to return a whole bunch of properties of an object
//! in a JSON response. Oftentimes, you as a user of this API are only interested in
//! a few of those and don't really need others.
//! To facilitate this, REST services typically support passing the list of properties
//! the client is interested in through the `fields` query parameter.
//! See examples of this pattern [here](https://yandex.com/dev/disk-api/doc/en/reference/all-files)
//! and [here](https://restcountries.com/#endpoints-filter-response).
//! <br>
//! Extruct offers two simple-to-use procedural macros that can be useful in implementing
//! wrappers around REST API that can retrieve only specific properties from the backend.
//!
//! The first macro is a derive macro [`Fields`](macro@Fields). It applies to structs with named
//! fields and implements the `Fields` trait that returns a list of fields' names as string
//! literals.
//!
//! The second macro is an attribute macro [`extruct_from`].
//! It can be used when there exists a "superstruct" that contains all possible fields.
//! In this case, when defining your own struct which contains only a subset of all
//! those fields you can use [`extruct_from`] which will implement the
//! [`std::convert::From`](https://doc.rust-lang.org/std/convert/trait.From.html) trait
//! converting an instance of the superstruct into an instance of your struct by converting
//! all fields from the original struct into fields with the same name of the substruct.
//!
//! Besides being handy for turning "full" objects into "partial", this ensures that all
//! fields are named the same and their types are compatible. To prove this, [`extruct_from`]
//! implements the [`ExtructedFrom`] trait which extends [`std::convert::From`](https://doc.rust-lang.org/std/convert/trait.From.html)
//! and verifies that the superstruct is not only convertible into substruct but also that
//! all the respective fields have same names.
//!
//! ## Examples
//! ```rust
//! # use extruct::ExtructedFrom;
//! # use extruct::Fields;
//! # use extruct::extruct_from;
//! #[derive(Fields)]
//! struct SuperStruct {
//!     one_field: String,
//!     another_field: u32,
//!     and_one_more: char,
//! }
//!
//! #[derive(Fields)]
//! #[extruct_from(SuperStruct)]
//! struct SubStruct {
//!     and_one_more: String,
//! }
//!
//! fn convert_preserving_names<T, S>(sup: S) -> T
//! where
//!     T: ExtructedFrom<S>,
//! {
//!     sup.into()
//! }
//!
//! assert_eq!(SuperStruct::fields(), ["one_field", "another_field", "and_one_more"]);
//! assert_eq!(SubStruct::fields(), ["and_one_more"]);
//!
//! let sup = SuperStruct {
//!     one_field: "str".to_owned(),
//!     another_field: 1135,
//!     and_one_more: 'x',
//! };
//!
//! let sub: SubStruct = convert_preserving_names(sup);
//! assert_eq!(sub.and_one_more, "x".to_owned());
//! ```
//!
//! # Notes
//! The [`Fields`](macro@Fields) derive macro can be applied to named structs and unit structs,
//! but unnamed structs can only be annotated with `#[derive(Fields)]` if they are empty.
//!
//! The [`extruct_from`] attribute macro can only be applied to non-generic named structs
//! and can only reference a concrete (non-generic) struct as a superstruct.
//! This limitation holds because the macro does not have visibility into the definition
//! of the superstruct and therefore would not be able to specify trait bounds for generic
//! fields when implementing the [`std::convert::From`](https://doc.rust-lang.org/std/convert/trait.From.html) trait.
//! If you want to use a specific instantiation of a generic struct as a superstruct, you
//! can use a type alias like so:
//! ```rust
//! # use extruct::Fields;
//! # use extruct::extruct_from;
//! // A generic struct cannot be referenced by the extruct_from() attribute macro...
//! struct GenericStruct<T, S> {
//!     one_field: T,
//!     another_field: u32,
//!     and_one_more: S,
//! }
//!
//! // ... but a non-generic type alias can be referenced by the extruct_from()
//! // attribute macro just fine
//! type ConcreteStruct = GenericStruct<String, char>;
//!
//! #[extruct_from(ConcreteStruct)]
//! struct SubStruct {
//!     and_one_more: String,
//! }
//!
//! let sup = ConcreteStruct {
//!     one_field: "str".to_owned(),
//!     another_field: 1135,
//!     and_one_more: 'x',
//! };
//!
//! let sub: SubStruct = sup.into();
//! assert_eq!(sub.and_one_more, "x".to_owned());
//! ```

#[cfg(any(feature = "extruct_from", doc))]
#[doc(inline)]
pub use extruct_core::ExtructedFrom;
#[cfg(any(feature = "fields", doc))]
#[doc(inline)]
pub use extruct_core::Fields;
#[cfg(any(feature = "extruct_from", doc))]
#[doc(inline)]
pub use extruct_macros::extruct_from;
#[cfg(any(feature = "fields", doc))]
#[doc(inline)]
pub use extruct_macros::Fields;