diff --git a/Cargo.lock b/Cargo.lock index c228484..41b03d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -272,9 +272,9 @@ dependencies = [ [[package]] name = "stacksafe" -version = "0.1.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9c1172965d317e87ddb6d364a040d958b40a1db82b6ef97da26253a8b3d090" +checksum = "e5481855df765c006135651b88e666edd4f08e176183052d2cb8628450873acb" dependencies = [ "stacker", "stacksafe-macro", @@ -282,9 +282,9 @@ dependencies = [ [[package]] name = "stacksafe-macro" -version = "0.1.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172175341049678163e979d9107ca3508046d4d2a7c6682bee46ac541b17db69" +checksum = "4825bd5b513e9bc047a10ffc1680d1203ef548bdccd633d633a15630f01d126f" dependencies = [ "proc-macro-error2", "quote", diff --git a/Cargo.toml b/Cargo.toml index eeae8af..3eacca0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ repository = "https://github.com/fast/traversable" rust-version = "1.85.0" [workspace.dependencies] -traversable-derive = { version = "0.1.0", path = "traversable-derive" } +traversable-derive = { version = "=0.1.0", path = "traversable-derive" } [workspace.lints.rust] unknown_lints = "deny" diff --git a/traversable-derive/Cargo.toml b/traversable-derive/Cargo.toml index 105d4b3..fdc32df 100644 --- a/traversable-derive/Cargo.toml +++ b/traversable-derive/Cargo.toml @@ -16,10 +16,14 @@ name = "traversable-derive" version = "0.1.0" +description = "Procedural macro to derive Traversable and TraversableMut" +documentation = "https://docs.rs/traversable-derive" +keywords = ["visitor", "traverse", "traversable"] +readme = "README.md" + edition.workspace = true homepage.workspace = true license.workspace = true -readme.workspace = true repository.workspace = true rust-version.workspace = true diff --git a/traversable-derive/LICENSE b/traversable-derive/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/traversable-derive/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/traversable-derive/README.md b/traversable-derive/README.md new file mode 100644 index 0000000..4669c15 --- /dev/null +++ b/traversable-derive/README.md @@ -0,0 +1,23 @@ +# traversable-derive + +[![Crates.io][crates-badge]][crates-url] +[![Documentation][docs-badge]][docs-url] +[![MSRV 1.85][msrv-badge]](https://www.whatrustisit.com) +[![Apache 2.0 licensed][license-badge]][license-url] +[![Build Status][actions-badge]][actions-url] + +[crates-badge]: https://img.shields.io/crates/v/traversable-derive.svg +[crates-url]: https://crates.io/crates/traversable-derive +[docs-badge]: https://docs.rs/traversable-derive/badge.svg +[msrv-badge]: https://img.shields.io/badge/MSRV-1.85-green?logo=rust +[docs-url]: https://docs.rs/traversable-derive +[license-badge]: https://img.shields.io/crates/l/traversable-derive +[license-url]: LICENSE +[actions-badge]: https://github.com/fast/traversable/workflows/CI/badge.svg +[actions-url]:https://github.com/fast/traversable/actions?query=workflow%3ACI + +This is an implementation crate for the [`traversable`](https://crates.io/crates/traversable) library. + +Please refer to the main [`traversable`](https://crates.io/crates/traversable) crate for documentation and usage examples. + +This crate contains procedural macros that derive `Traversable` and `TraversableMut` implementations. diff --git a/traversable-derive/src/lib.rs b/traversable-derive/src/lib.rs index 643ac76..7b4a8a3 100644 --- a/traversable-derive/src/lib.rs +++ b/traversable-derive/src/lib.rs @@ -40,7 +40,7 @@ use syn::Result; use syn::Token; use syn::Variant; use syn::parse_macro_input; -use syn::parse_str; +use syn::parse_quote; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::token::Mut; @@ -198,6 +198,11 @@ impl Param { } } +#[inline(always)] +fn resolve_crate_name() -> Path { + parse_quote!(::traversable) +} + fn impl_traversable(input: DeriveInput, mutable: bool) -> Result { let mut params = Params::from_attrs(input.attrs, "traverse")?; params.validate(&["skip"])?; @@ -226,11 +231,13 @@ fn impl_traversable(input: DeriveInput, mutable: bool) -> Result { Span::call_site(), ); + let crate_name = resolve_crate_name(); + let enter_self = if skip_visit_self { None } else { Some(quote! { - ::traversable::#visitor::#enter_method(visitor, self)?; + #crate_name::#visitor::#enter_method(visitor, self)?; }) }; @@ -238,7 +245,7 @@ fn impl_traversable(input: DeriveInput, mutable: bool) -> Result { None } else { Some(quote! { - ::traversable::#visitor::#leave_method(visitor, self)?; + #crate_name::#visitor::#leave_method(visitor, self)?; }) }; @@ -274,8 +281,8 @@ fn impl_traversable(input: DeriveInput, mutable: bool) -> Result { }; Ok(quote! { - impl #impl_generics ::traversable::#impl_trait for #name #ty_generics #where_clause { - fn #method( + impl #impl_generics #crate_name::#impl_trait for #name #ty_generics #where_clause { + fn #method( & #mut_modifier self, visitor: &mut V ) -> ::core::ops::ControlFlow { @@ -402,18 +409,19 @@ fn traverse_field(value: &TokenStream, field: Field, mutable: bool) -> Result(), - )?; + let crate_name = resolve_crate_name(); - Ok(quote! { - #traverse_fn(#value, visitor)?; - }) + match params.param("with")? { + None => Ok(if mutable { + quote! { #crate_name::TraversableMut::traverse_mut(#value, visitor)?; } + } else { + quote! { #crate_name::Traversable::traverse(#value, visitor)?; } + }), + Some(traverse_fn) => { + let traverse_fn = traverse_fn.string_literal()?.parse::()?; + Ok(quote! { + #traverse_fn(#value, visitor)?; + }) + } + } } diff --git a/traversable/Cargo.toml b/traversable/Cargo.toml index 8f9062b..b6547fc 100644 --- a/traversable/Cargo.toml +++ b/traversable/Cargo.toml @@ -16,6 +16,10 @@ name = "traversable" version = "0.1.0" +description = "Visitor Pattern over Traversable data structures" +documentation = "https://docs.rs/traversable" +keywords = ["visitor", "traverse", "traversable"] + edition.workspace = true homepage.workspace = true license.workspace = true @@ -49,14 +53,14 @@ traverse-std = [] # Implement Traversal for third-party library types. ordered-float-5 = ["dep:ordered-float-5"] -stacksafe-01 = ["dep:stacksafe-01"] +stacksafe-1 = ["dep:stacksafe-1"] [dependencies] traversable-derive = { workspace = true, optional = true } # Optional dependencies for third-party library support ordered-float-5 = { version = "5.1", default-features = false, optional = true, package = "ordered-float" } -stacksafe-01 = { version = "0.1", default-features = false, optional = true, package = "stacksafe" } +stacksafe-1 = { version = "1", default-features = false, optional = true, package = "stacksafe" } [lints] workspace = true diff --git a/traversable/src/impls/mod.rs b/traversable/src/impls/mod.rs index a195c50..52c9cb1 100644 --- a/traversable/src/impls/mod.rs +++ b/traversable/src/impls/mod.rs @@ -14,5 +14,5 @@ #[cfg(feature = "ordered-float-5")] mod ordered_float_5; -#[cfg(feature = "stacksafe-01")] -mod stacksafe_01; +#[cfg(feature = "stacksafe-1")] +mod stacksafe_1; diff --git a/traversable/src/impls/stacksafe_01.rs b/traversable/src/impls/stacksafe_1.rs similarity index 88% rename from traversable/src/impls/stacksafe_01.rs rename to traversable/src/impls/stacksafe_1.rs index 0e73298..361ed73 100644 --- a/traversable/src/impls/stacksafe_01.rs +++ b/traversable/src/impls/stacksafe_1.rs @@ -14,21 +14,21 @@ use core::ops::ControlFlow; -use stacksafe_01::StackSafe; -use stacksafe_01::stacksafe; +use stacksafe_1::StackSafe; +use stacksafe_1::stacksafe; use crate::Traversable; use crate::TraversableMut; impl Traversable for StackSafe { - #[stacksafe(crate = stacksafe_01)] + #[stacksafe(crate = stacksafe_1)] fn traverse(&self, visitor: &mut V) -> ControlFlow { (**self).traverse(visitor) } } impl TraversableMut for StackSafe { - #[stacksafe(crate = stacksafe_01)] + #[stacksafe(crate = stacksafe_1)] fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { (**self).traverse_mut(visitor) }