diff --git a/lox-macros/src/lib.rs b/lox-macros/src/lib.rs index 9d2fced..650bed2 100644 --- a/lox-macros/src/lib.rs +++ b/lox-macros/src/lib.rs @@ -16,9 +16,7 @@ mod derives; mod mesh; -/// See [`lox::mesh_macro`][dummy] for documentation. -/// -/// [dummy]: ../lox/macro.mesh_macro.html +// See [`lox::mesh`][../lox/macro.mesh.html] for documentation. #[proc_macro] pub fn mesh(input: TokenStream) -> TokenStream { use crate::mesh::MeshInput; @@ -30,12 +28,7 @@ pub fn mesh(input: TokenStream) -> TokenStream { } -/// Custom derive for the `Empty` trait. -/// -/// See [the documentation of the `Empty` trait in `lox`][trait] for more information -/// about this derive. -/// -/// [trait]: ../lox/traits/trait.Empty.html +// See main crate (`lox`) for documentation. #[proc_macro_derive(Empty)] pub fn derive_empty(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as DeriveInput); @@ -45,12 +38,7 @@ pub fn derive_empty(input: TokenStream) -> TokenStream { } -/// Custom derive for the `MemSink` trait. -/// -/// See [the documentation of the `MemSink` trait in `lox`][trait] for more -/// information about this derive. -/// -/// [trait]: ../lox/io/trait.MemSink.html +// See main crate (`lox`) for documentation. #[proc_macro_derive(MemSink, attributes(lox))] pub fn derive_mem_sink(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as DeriveInput); @@ -60,12 +48,7 @@ pub fn derive_mem_sink(input: TokenStream) -> TokenStream { .into() } -/// Custom derive for the `MemSource` trait. -/// -/// See [the documentation of the `MemSource` trait in `lox`][trait] for more -/// information about this derive. -/// -/// [trait]: ../lox/io/trait.MemSource.html +// See main crate (`lox`) for documentation. #[proc_macro_derive(MemSource, attributes(lox))] pub fn derive_mem_source(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as DeriveInput); diff --git a/src/io/mod.rs b/src/io/mod.rs index 227ced3..c88a73d 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -1245,118 +1245,8 @@ where /// /// # Deriving /// -/// You can easily derive this trait for your own types. To derive this trait, -/// you have to attach `#[derive(MemSink)]` to your struct definition (note: -/// currently, the trait can only be derived for structs with named fields). -/// You also have to annotate your fields with `#[lox(...)]` attributes to tell -/// the derive macro what a field should be used for. Example: -/// -/// ``` -/// use lox::{ -/// MemSink, VertexHandle, -/// cgmath::Point3, -/// ds::HalfEdgeMesh, -/// map::DenseMap, -/// }; -/// -/// -/// #[derive(MemSink)] -/// struct MyMesh { -/// #[lox(core_mesh)] -/// mesh: HalfEdgeMesh, -/// -/// #[lox(vertex_position)] -/// positions: DenseMap>, -/// } -/// ``` -/// -/// There is one required field: the core mesh field. That field's type has to -/// implement several mesh traits, in particular `MeshMut` and `TriMeshMut`. -/// You have to annotate that mesh with `#[lox(core_mesh)]`. -/// -/// Additionally, you can have fields for each mesh property, like vertex -/// position or face colors. The type of those fields has to implement -/// `PropStoreMut` with a compatible element type. You have to annotate these -/// property fields with the corresponding attribute. The available properties -/// are: -/// -/// - `vertex_position` -/// - `vertex_normal` -/// - `vertex_color` -/// - `face_normal` -/// - `face_color` -/// -/// Furthermore, there are some configurations (like the cast mode) that can be -/// configured via `lox(...)` attributes as well. See below for more -/// information. -/// -/// -/// ### Cast modes -/// -/// You can set a *cast mode* for each field. A `MemSink` has to be able to -/// "handle" any primitive type as the source is allowed to call the property -/// methods with any type. The sink can handle types either by casting or by -/// returning an error. The field's cast mode determines which casts are -/// allowed and which are not. Possible cast modes: -/// -/// - `cast = "none"` -/// - `cast = "lossless"` -/// - `cast = "rounding"` -/// - `cast = "clamping"` -/// - `cast = "lossy"` (*default*) -/// -/// The `none` mode does not allow casting at all. If the type provided by the -/// source does not match the type in your struct, an error is returned. All -/// other modes correspond to the cast modes in the [`cast` -/// module][crate::cast]. -/// -/// Note that the cast modes are used by `derive(MemSource)` as well. -/// -/// You can specify the cast mode either per field or globally on the whole -/// struct. The mode of the struct applies to all fields that don't have a -/// field-specific mode. -/// -/// ``` -/// # use lox::{ -/// # MemSink, VertexHandle, -/// # cgmath::{Point3, Vector3}, -/// # ds::HalfEdgeMesh, -/// # map::DenseMap, -/// # }; -/// # -/// #[derive(MemSink)] -/// #[lox(cast = "none")] -/// struct MyMesh { -/// #[lox(core_mesh)] -/// mesh: HalfEdgeMesh, -/// -/// #[lox(vertex_position)] -/// positions: DenseMap>, -/// -/// #[lox(vertex_normal, cast = "lossy")] -/// normals: DenseMap>, -/// } -/// ``` -/// -/// In this example, the vertex positions inherit the "struct global" cast mode -/// (`none`), while the vertex normals override that mode to `lossy`. -/// -/// -/// ### Exact traits required for each field -/// -/// Traits required for the `core_mesh` field: -/// - TODO -/// -/// Traits required for property fields. For type `T` of the field: -/// - `T` must implement [`PropStoreMut`][crate::map::PropStoreMut] (with -/// fitting handle type). Additionally: -/// - For `vertex_position`: `T::Target` must implement -/// [`Pos3Like`][crate::prop::Pos3Like]. -/// - For `*_normal`: `T::Target` must implement -/// [`Vec3Like`][crate::prop::Vec3Like]. -/// - For `*_color`: `T::Target` must implement -/// [`ColorLike`][crate::prop::ColorLike] and `T::Target::Channel` must -/// implement [`Primitive`]. +/// You can easily derive this trait for your own types. See [the derive +/// macro's documentation](../derive.MemSink.html) for more information. pub trait MemSink { // ======================================================================= // ===== Mesh connectivity @@ -1606,52 +1496,8 @@ where /// /// # Deriving /// -/// You can easily derive this trait for your own types. To derive this trait, -/// you have to attach `#[derive(MemSource)]` to your struct definition (note: -/// currently, the trait can only be derived for structs with named fields). -/// You also have to annotate your fields with `#[lox(...)]` attributes to tell -/// the derive macro what a field should be used for. Example: -/// -/// ``` -/// use lox::{ -/// MemSource, VertexHandle, -/// cgmath::Point3, -/// ds::SharedVertexMesh, -/// map::DenseMap, -/// }; -/// -/// -/// #[derive(MemSource)] -/// struct MyMesh { -/// #[lox(core_mesh)] -/// mesh: SharedVertexMesh, -/// -/// #[lox(vertex_position)] -/// positions: DenseMap>, -/// } -/// ``` -/// -/// Deriving this trait works very similar to deriving [`MemSink`]. See its -/// documentation for more information on the custom derive. -/// -/// -/// ### Exact traits required for each field -/// -/// Traits required for the `core_mesh` field: -/// - TODO -/// -/// Traits required for property fields. For type `T` of the field: -/// - `T` must implement [`PropStore`][crate::map::PropStore] (with fitting -/// handle type). Additionally: -/// - For `vertex_position`: `T::Target` must implement -/// [`Pos3Like`][crate::prop::Pos3Like] and `T::Target::Scalar` must -/// implement [`Primitive`]. -/// - For `*_normal`: `T::Target` must implement -/// [`Vec3Like`][crate::prop::Vec3Like] and `T::Target::Scalar` must -/// implement [`Primitive`]. -/// - For `*_color`: `T::Target` must implement -/// [`ColorLike`][crate::prop::ColorLike] and `T::Target::Channel` must -/// implement [`Primitive`]. +/// You can easily derive this trait for your own types. See [the derive +/// macro's documentation](../derive.MemSource.html) for more information. pub trait MemSource { /// The type of the core mesh. type CoreMesh: TriMesh + BasicAdj; diff --git a/src/lib.rs b/src/lib.rs index 2ba658e..9013c09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,15 +77,193 @@ pub(crate) mod sealed { // ===== Macros // =========================================================================== +/// Derive macro for the [`Empty` trait][traits::Empty]. +/// +/// ``` +/// use lox::Empty; // this imports the custom-derive and not the trait! +/// +/// #[derive(Empty)] +/// struct MyStruct { +/// a: Vec, // => `vec![]` +/// b: Option, // => `None` +/// c: (), // => `()` +/// } +/// ``` +/// +/// This can only be derived for structs. All struct fields need to implement +/// `Empty` in order for the derive to work. If your struct has generic +/// parameters, they won't be bounded with `Empty` in the generated impl block. +/// This is useful most of the time, because things like `Vec` and +/// `Option` don't require `T: Empty` to implement `Empty`. But this means +/// that you sometimes have to add a global `Empty` bound to your parameter or +/// implement `Empty` manually. pub use lox_macros::Empty; -pub use lox_macros::MemSink; -pub use lox_macros::MemSource; +/// Derive macro for [the `MemSink` trait][io::MemSink]. +/// +/// You can easily derive `MemSink` for your own types. To do that, you have to +/// attach `#[derive(MemSink)]` to your struct definition (note: currently, the +/// trait can only be derived for structs with named fields). You also have to +/// annotate your fields with `#[lox(...)]` attributes to tell the derive macro +/// what a field should be used for. Example: +/// +/// ``` +/// use lox::{ +/// MemSink, VertexHandle, +/// cgmath::Point3, +/// ds::HalfEdgeMesh, +/// map::DenseMap, +/// }; +/// +/// +/// #[derive(MemSink)] +/// struct MyMesh { +/// #[lox(core_mesh)] +/// mesh: HalfEdgeMesh, +/// +/// #[lox(vertex_position)] +/// positions: DenseMap>, +/// } +/// ``` +/// +/// There is one required field: the core mesh field. That field's type has to +/// implement several mesh traits, in particular `MeshMut` and `TriMeshMut`. +/// You have to annotate that mesh with `#[lox(core_mesh)]`. +/// +/// Additionally, you can have fields for each mesh property, like vertex +/// position or face colors. The type of those fields has to implement +/// `PropStoreMut` with a compatible element type. You have to annotate these +/// property fields with the corresponding attribute. The available properties +/// are: +/// +/// - `vertex_position` +/// - `vertex_normal` +/// - `vertex_color` +/// - `face_normal` +/// - `face_color` +/// +/// Furthermore, there are some configurations (like the cast mode) that can be +/// configured via `lox(...)` attributes as well. See below for more +/// information. +/// +/// +/// ## Cast modes +/// +/// You can set a *cast mode* for each field. A `MemSink` has to be able to +/// "handle" any primitive type as the source is allowed to call the property +/// methods with any type. The sink can handle types either by casting or by +/// returning an error. The field's cast mode determines which casts are +/// allowed and which are not. Possible cast modes: +/// +/// - `cast = "none"` +/// - `cast = "lossless"` +/// - `cast = "rounding"` +/// - `cast = "clamping"` +/// - `cast = "lossy"` (*default*) +/// +/// The `none` mode does not allow casting at all. If the type provided by the +/// source does not match the type in your struct, an error is returned. All +/// other modes correspond to the cast modes in the [`cast` +/// module][crate::cast]. +/// +/// Note that the cast modes are used by `derive(MemSource)` as well. +/// +/// You can specify the cast mode either per field or globally on the whole +/// struct. The mode of the struct applies to all fields that don't have a +/// field-specific mode. +/// +/// ``` +/// # use lox::{ +/// # MemSink, VertexHandle, +/// # cgmath::{Point3, Vector3}, +/// # ds::HalfEdgeMesh, +/// # map::DenseMap, +/// # }; +/// # +/// #[derive(MemSink)] +/// #[lox(cast = "none")] +/// struct MyMesh { +/// #[lox(core_mesh)] +/// mesh: HalfEdgeMesh, +/// +/// #[lox(vertex_position)] +/// positions: DenseMap>, +/// +/// #[lox(vertex_normal, cast = "lossy")] +/// normals: DenseMap>, +/// } +/// ``` +/// +/// In this example, the vertex positions inherit the "struct global" cast mode +/// (`none`), while the vertex normals override that mode to `lossy`. +/// +/// +/// ### Exact traits required for each field +/// +/// Traits required for the `core_mesh` field: +/// - TODO +/// +/// Traits required for property fields. For type `T` of the field: +/// - `T` must implement [`PropStoreMut`][crate::map::PropStoreMut] (with +/// fitting handle type). Additionally: +/// - For `vertex_position`: `T::Target` must implement +/// [`Pos3Like`][crate::prop::Pos3Like]. +/// - For `*_normal`: `T::Target` must implement +/// [`Vec3Like`][crate::prop::Vec3Like]. +/// - For `*_color`: `T::Target` must implement +/// [`ColorLike`][crate::prop::ColorLike] and `T::Target::Channel` must +/// implement [`Primitive`]. +pub use lox_macros::MemSink; -// Sadly, rustdoc is a bit buggy when it comes to reexporting proc macros. So -// when rustdoc runs, we use a dummy macro. When the crate is compiled as -// usual, we will reexport the proc macro. TODO: check if fixed -pub use lox_macros::mesh as mesh; +/// Derive macro for [the `MemSource` trait][io::MemSource]. +/// +/// You can easily derive `MemSource` for your own types. To do that, you have +/// to attach `#[derive(MemSource)]` to your struct definition (note: +/// currently, the trait can only be derived for structs with named fields). +/// You also have to annotate your fields with `#[lox(...)]` attributes to tell +/// the derive macro what a field should be used for. Example: +/// +/// ``` +/// use lox::{ +/// MemSource, VertexHandle, +/// cgmath::Point3, +/// ds::SharedVertexMesh, +/// map::DenseMap, +/// }; +/// +/// +/// #[derive(MemSource)] +/// struct MyMesh { +/// #[lox(core_mesh)] +/// mesh: SharedVertexMesh, +/// +/// #[lox(vertex_position)] +/// positions: DenseMap>, +/// } +/// ``` +/// +/// Deriving this trait works very similar to deriving [`MemSink`]. See its +/// documentation for more information on the custom derive. +/// +/// +/// ### Exact traits required for each field +/// +/// Traits required for the `core_mesh` field: +/// - TODO +/// +/// Traits required for property fields. For type `T` of the field: +/// - `T` must implement [`PropStore`][crate::map::PropStore] (with fitting +/// handle type). Additionally: +/// - For `vertex_position`: `T::Target` must implement +/// [`Pos3Like`][crate::prop::Pos3Like] and `T::Target::Scalar` must +/// implement [`Primitive`]. +/// - For `*_normal`: `T::Target` must implement +/// [`Vec3Like`][crate::prop::Vec3Like] and `T::Target::Scalar` must +/// implement [`Primitive`]. +/// - For `*_color`: `T::Target` must implement +/// [`ColorLike`][crate::prop::ColorLike] and `T::Target::Channel` must +/// implement [`Primitive`]. +pub use lox_macros::MemSource; /// Convenience macro to quickly create a small mesh. /// @@ -195,9 +373,4 @@ pub use lox_macros::mesh as mesh; /// faces: [], /// }; /// ``` -#[cfg(rustdoc)] -#[macro_export] -macro_rules! mesh_macro { - // The real implementation is in `lox_macros` and it's reexported above. - (/* proc macro */) => ( /* proc macro */ ) -} +pub use lox_macros::mesh; diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 05f1934..f4da3d5 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -30,26 +30,8 @@ pub mod adj; /// /// # Deriving /// -/// This trait can automatically be derived: -/// -/// ``` -/// use lox::Empty; // this imports the custom-derive and not the trait! -/// -/// #[derive(Empty)] -/// struct MyStruct { -/// a: Vec, // => `vec![]` -/// b: Option, // => `None` -/// c: (), // => `()` -/// } -/// ``` -/// -/// This can only be derived for structs. All struct fields need to implement -/// `Empty` in order for the derive to work. If your struct has generic -/// parameters, they won't be bounded with `Empty` in the generated impl block. -/// This is useful most of the time, because things like `Vec` and -/// `Option` don't require `T: Empty` to implement `Empty`. But this means -/// that you sometimes have to add a global `Empty` bound to your parameter or -/// implement `Empty` manually. +/// This trait can automatically be derived. See [the derive +/// macro](../derive.Empty.html) for more information on that. pub trait Empty { /// Returns an empty value of this type. fn empty() -> Self;