Skip to content

Commit

Permalink
Add docs to all top level items (#54)
Browse files Browse the repository at this point in the history
This adds high level docs to all top level items. The most relevant
sections are on the root module and `#[derive(Reflect)]`.

Part of #4

Co-authored-by: Benjamin Bouvier <[email protected]>
  • Loading branch information
davidpdrsn and bnjbvr authored Dec 16, 2022
1 parent 8ff29ff commit a70073d
Show file tree
Hide file tree
Showing 15 changed files with 523 additions and 12 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/rust-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ jobs:
- name: cargo hack check
run: cargo hack check --each-feature --no-dev-deps --all

check-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
profile: minimal
- uses: Swatinem/rust-cache@v1
- name: cargo doc
env:
RUSTDOCFLAGS: "-D broken-intra-doc-links"
run: cargo doc --all-features --no-deps

no-std-build:
runs-on: ubuntu-latest
steps:
Expand Down
3 changes: 3 additions & 0 deletions crates/mirror-mirror-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ proc-macro2 = "1.0.47"
quote = "1.0.21"
syn = { version = "1.0.102", features = ["full", "visit"] }

[dev-dependencies]
mirror-mirror = { path = "../mirror-mirror", version = "0.1", default-features = false }

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
198 changes: 198 additions & 0 deletions crates/mirror-mirror-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,204 @@ use syn::parse::Parse;

mod derive_reflect;

/// Derive an implementation of `Reflect` and other appropriate traits.
///
/// # Structs
///
/// On structs `#[derive(Reflect)]` will also derive `Struct` and `FromReflect`.
///
/// ```
/// use mirror_mirror::Reflect;
///
/// #[derive(Reflect, Clone, Debug)]
/// struct Foo {
/// a: i32,
/// b: bool,
/// c: String,
/// }
/// ```
///
/// Unit structs are treated as tuple structs with no fields.
///
/// # Tuple structs
///
/// On tuple structs `#[derive(Reflect)]` will also derive `TupleStruct` and `FromReflect`.
///
/// ```
/// use mirror_mirror::Reflect;
///
/// #[derive(Reflect, Clone, Debug)]
/// struct Foo(i32, bool, String);
/// ```
///
/// # Enums
///
/// On enums `#[derive(Reflect)]` will also derive `Enum` and `FromReflect`.
///
/// ```
/// use mirror_mirror::Reflect;
///
/// #[derive(Reflect, Clone, Debug)]
/// enum Foo {
/// A(i32),
/// B { b: bool },
/// C,
/// }
/// ```
///
/// # Options
///
/// ## `opt_out`
///
/// By default types are required to implement `Clone` and `Debug`. You can opt-out of these
/// requirements with `#[reflect(opt_out(Clone, Debug))]`
///
/// ```
/// use mirror_mirror::Reflect;
///
/// #[derive(Reflect)]
/// #[reflect(opt_out(Debug, Clone))]
/// struct Foo(i32);
/// ```
///
/// This changes the implementation of `Reflect::clone_reflect` and `Reflect::debug` to something
/// that works for any type but is less performant.
///
/// You can also opt-out of deriving `FromReflect` so you can provide you own implementation:
///
/// ```
/// use mirror_mirror::{Reflect, FromReflect};
///
/// #[derive(Reflect, Debug, Clone)]
/// #[reflect(opt_out(FromReflect))]
/// struct Foo(i32);
///
/// impl FromReflect for Foo {
/// fn from_reflect(value: &dyn Reflect) -> Option<Self> {
/// Some(Self(*value.downcast_ref::<i32>()?))
/// }
/// }
/// ```
///
/// ## `skip`
///
/// You can exclude fields or variants from being reflected with `#[reflect(skip)]`. The type of the skipped field/variant is
/// required to implement `Default` by the default `FromReflect` implementation.
///
/// ```
/// use mirror_mirror::{Reflect, FromReflect};
///
/// #[derive(Reflect, Debug, Clone)]
/// struct Foo {
/// #[reflect(skip)]
/// not_reflect: NotReflect,
/// }
///
/// #[derive(Reflect, Debug, Clone)]
/// struct Bar(#[reflect(skip)] NotReflect);
///
/// #[derive(Reflect, Debug, Clone)]
/// enum Baz {
/// #[reflect(skip)]
/// OnVariant(NotReflect),
///
/// OnTupleField(#[reflect(skip)] NotReflect),
///
/// OnStructField {
/// #[reflect(skip)]
/// not_reflect: NotReflect,
/// }
/// }
///
/// // A type that isn't compatible with reflection
/// #[derive(Debug, Clone, Default)]
/// struct NotReflect;
/// ```
///
/// ## `from_reflect_with`
///
/// You can override `FromReflect` for a single field by specifying a function to do the
/// conversion:
///
/// ```
/// use mirror_mirror::{Reflect, FromReflect};
///
/// #[derive(Reflect, Debug, Clone)]
/// struct Foo {
/// #[reflect(from_reflect_with(n_from_reflect))]
/// n: i32,
/// }
///
/// fn n_from_reflect(field: &dyn Reflect) -> Option<i32> {
/// Some(*field.downcast_ref::<i32>()?)
/// }
/// ```
///
/// ## `meta`
///
/// Metadata associated with types or enum variants can be added with `#[reflect(meta(...))]`
///
/// ```
/// use mirror_mirror::{
/// Reflect,
/// key_path,
/// key_path::GetTypePath,
/// FromReflect,
/// type_info::{GetMeta, Typed},
/// };
///
/// #[derive(Reflect, Debug, Clone)]
/// #[reflect(meta(
/// // a comma separated list of `key = value` pairs.
/// //
/// // `key` must be an identifier and `value` can be anything that
/// // implements `Reflect`
/// item_key = "item value",
/// ))]
/// struct Foo {
/// #[reflect(meta(field_key = 1337))]
/// n: i32,
/// }
///
/// // Access the metadata through the type information
/// let type_info = <Foo as Typed>::type_info();
///
/// assert_eq!(
/// type_info.get_meta::<String>("item_key").unwrap(),
/// "item value",
/// );
///
/// assert_eq!(
/// type_info
/// .as_struct()
/// .unwrap()
/// .field_type("n")
/// .unwrap()
/// .get_meta::<i32>("field_key")
/// .unwrap(),
/// 1337,
/// );
/// ```
///
/// ## `crate_name`
///
/// You can specify a "use path" for `mirror_mirror` with `crate_name`. This is useful if you're
/// using a library that re-exports `mirror_mirror`'s derive macro:
///
/// ```
/// # use mirror_mirror as some_library;
/// use some_library::Reflect;
///
/// #[derive(Reflect, Debug, Clone)]
/// #[reflect(crate_name(some_library))]
/// struct Foo {
/// n: i32,
/// }
/// ```
///
/// This causes the macro generate paths like `some_library::FromReflect`.
///
/// [`Reflect`]: crate::Reflect
#[proc_macro_derive(Reflect, attributes(reflect))]
pub fn derive_reflect(item: TokenStream) -> TokenStream {
expand_with(item, derive_reflect::expand)
Expand Down
1 change: 1 addition & 0 deletions crates/mirror-mirror/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::fmt;
use crate::iter::ValueIterMut;
use crate::Reflect;

/// A reflected array type.
pub trait Array: Reflect {
fn get(&self, index: usize) -> Option<&dyn Reflect>;

Expand Down
3 changes: 3 additions & 0 deletions crates/mirror-mirror/src/enum_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ use crate::TypeRoot;
use crate::Typed;
use crate::Value;

/// A reflected enum type.
///
/// Will be implemented by `#[derive(Reflect)]` on enums.
pub trait Enum: Reflect {
fn variant_name(&self) -> &str;

Expand Down
2 changes: 2 additions & 0 deletions crates/mirror-mirror/src/get_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ use crate::Tuple;
use crate::TupleStruct;
use crate::Value;

/// Helper trait for accessing and downcasting fields on reflected values.
pub trait GetField<'a, K, M> {
fn get_field<T>(self, key: K) -> Option<&'a T>
where
T: Reflect;
}

/// Helper trait for mutably accessing and downcasting fields on reflected values.
pub trait GetFieldMut<'a, K, M> {
fn get_field_mut<T>(self, key: K) -> Option<&'a mut T>
where
Expand Down
18 changes: 6 additions & 12 deletions crates/mirror-mirror/src/key_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,18 +240,12 @@ impl KeyPath {
self.path.push(Key::FieldAt(field.into()))
}

pub fn variant<S>(mut self, variant: S) -> Self
where
S: Into<String>,
{
pub fn variant(mut self, variant: impl Into<String>) -> Self {
self.push_variant(variant);
self
}

pub fn push_variant<S>(&mut self, variant: S)
where
S: Into<String>,
{
pub fn push_variant(&mut self, variant: impl Into<String>) {
self.path.push(Key::Variant(variant.into()));
}

Expand Down Expand Up @@ -328,13 +322,13 @@ pub fn get(field: impl Into<Value>) -> KeyPath {
KeyPath::default().get(field)
}

pub fn variant<S>(variant: S) -> KeyPath
where
S: Into<String>,
{
pub fn variant(variant: impl Into<String>) -> KeyPath {
KeyPath::default().variant(variant)
}

/// Convenience macro for creating [`KeyPath`]s.
///
/// Expands to calls to [`field`], [`get`], [`variant`], and methods on [`KeyPath`].
#[macro_export]
macro_rules! key_path {
// base case
Expand Down
Loading

0 comments on commit a70073d

Please sign in to comment.