1#![allow(unknown_lints)]
20#![deny(renamed_and_removed_lints)]
21#![deny(
22 clippy::all,
23 clippy::missing_safety_doc,
24 clippy::multiple_unsafe_ops_per_block,
25 clippy::undocumented_unsafe_blocks
26)]
27#![allow(clippy::type_complexity)]
29#![allow(clippy::uninlined_format_args)]
31#![deny(
32 rustdoc::bare_urls,
33 rustdoc::broken_intra_doc_links,
34 rustdoc::invalid_codeblock_attributes,
35 rustdoc::invalid_html_tags,
36 rustdoc::invalid_rust_codeblocks,
37 rustdoc::missing_crate_level_docs,
38 rustdoc::private_intra_doc_links
39)]
40#![recursion_limit = "128"]
41
42macro_rules! ident {
43 (($fmt:literal $(, $arg:expr)*), $span:expr) => {
44 syn::Ident::new(&format!($fmt $(, crate::util::to_ident_str($arg))*), $span)
45 };
46}
47
48mod derive;
49#[cfg(test)]
50mod output_tests;
51mod repr;
52mod util;
53
54use syn::{DeriveInput, Error};
55
56use crate::util::*;
57
58macro_rules! derive {
82 ($trait:ident => $outer:ident => $inner:path) => {
83 #[proc_macro_derive($trait, attributes(zerocopy))]
84 pub fn $outer(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
85 let ast = syn::parse_macro_input!(ts as DeriveInput);
86 let ctx = match Ctx::try_from_derive_input(ast) {
87 Ok(ctx) => ctx,
88 Err(e) => return e.into_compile_error().into(),
89 };
90 let ts = $inner(&ctx, Trait::$trait).into_ts();
91 let ts = const_block([Some(ts)]);
95 #[cfg(test)]
96 crate::util::testutil::check_hygiene(ts.clone());
97 ts.into()
98 }
99 };
100}
101
102trait IntoTokenStream {
103 fn into_ts(self) -> proc_macro2::TokenStream;
104}
105
106impl IntoTokenStream for proc_macro2::TokenStream {
107 fn into_ts(self) -> proc_macro2::TokenStream {
108 self
109 }
110}
111
112impl IntoTokenStream for Result<proc_macro2::TokenStream, Error> {
113 fn into_ts(self) -> proc_macro2::TokenStream {
114 match self {
115 Ok(ts) => ts,
116 Err(err) => err.to_compile_error(),
117 }
118 }
119}
120
121derive!(KnownLayout => derive_known_layout => crate::derive::known_layout::derive);
122derive!(Immutable => derive_immutable => crate::derive::derive_immutable);
123derive!(TryFromBytes => derive_try_from_bytes => crate::derive::try_from_bytes::derive_try_from_bytes);
124derive!(FromZeros => derive_from_zeros => crate::derive::from_bytes::derive_from_zeros);
125derive!(FromBytes => derive_from_bytes => crate::derive::from_bytes::derive_from_bytes);
126derive!(IntoBytes => derive_into_bytes => crate::derive::into_bytes::derive_into_bytes);
127derive!(Unaligned => derive_unaligned => crate::derive::unaligned::derive_unaligned);
128derive!(ByteHash => derive_hash => crate::derive::derive_hash);
129derive!(ByteEq => derive_eq => crate::derive::derive_eq);
130derive!(SplitAt => derive_split_at => crate::derive::derive_split_at);
131
132#[cfg_attr(zerocopy_unstable_linux, doc(hidden))]
133#[proc_macro_derive(most_traits, attributes(zerocopy))]
134pub fn most_traits(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
135 let ast = syn::parse_macro_input!(ts as DeriveInput);
136 let ctx = match Ctx::try_from_derive_input(ast) {
137 Ok(ctx) => ctx,
138 Err(e) => return e.into_compile_error().into(),
139 }
140 .skip_on_error();
141
142 let derives: [(fn(&Ctx, Trait) -> _, _); 6] = [
144 (crate::derive::known_layout::derive, Trait::KnownLayout),
145 (crate::derive::derive_immutable, Trait::Immutable),
146 (crate::derive::from_bytes::derive_from_bytes, Trait::FromBytes),
147 (crate::derive::into_bytes::derive_into_bytes, Trait::IntoBytes),
148 (crate::derive::derive_split_at, Trait::SplitAt),
149 (crate::derive::unaligned::derive_unaligned, Trait::Unaligned),
150 ];
151
152 let mut tokens = proc_macro2::TokenStream::new();
153 for (derive, t) in derives {
154 tokens.extend(derive(&ctx, t))
155 }
156
157 let ts = const_block([Some(tokens)]);
161 #[cfg(test)]
162 crate::util::testutil::check_hygiene(ts.clone());
163 ts.into()
164}
165
166#[deprecated(since = "0.8.0", note = "`FromZeroes` was renamed to `FromZeros`")]
168#[doc(hidden)]
169#[proc_macro_derive(FromZeroes)]
170pub fn derive_from_zeroes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
171 derive_from_zeros(ts)
172}
173
174#[deprecated(since = "0.8.0", note = "`AsBytes` was renamed to `IntoBytes`")]
176#[doc(hidden)]
177#[proc_macro_derive(AsBytes)]
178pub fn derive_as_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
179 derive_into_bytes(ts)
180}