// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
//
// Copyright 2019 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.

//! Derive macros for [zerocopy]'s traits.
//!
//! [zerocopy]: https://docs.rs/zerocopy

// Sometimes we want to use lints which were added after our MSRV.
// `unknown_lints` is `warn` by default and we deny warnings in CI, so without
// this attribute, any unknown lint would cause a CI failure when testing with
// our MSRV.
#![allow(unknown_lints)]
#![deny(renamed_and_removed_lints)]
#![deny(
    clippy::all,
    clippy::missing_safety_doc,
    clippy::multiple_unsafe_ops_per_block,
    clippy::undocumented_unsafe_blocks
)]
// We defer to own discretion on type complexity.
#![allow(clippy::type_complexity)]
// Inlining format args isn't supported on our MSRV.
#![allow(clippy::uninlined_format_args)]
#![deny(
    rustdoc::bare_urls,
    rustdoc::broken_intra_doc_links,
    rustdoc::invalid_codeblock_attributes,
    rustdoc::invalid_html_tags,
    rustdoc::invalid_rust_codeblocks,
    rustdoc::missing_crate_level_docs,
    rustdoc::private_intra_doc_links
)]
#![recursion_limit = "128"]

macro_rules! ident {
    (($fmt:literal $(, $arg:expr)*), $span:expr) => {
        syn::Ident::new(&format!($fmt $(, crate::util::to_ident_str($arg))*), $span)
    };
}

mod derive;
#[cfg(test)]
mod output_tests;
mod repr;
mod util;

use syn::{DeriveInput, Error};

use crate::util::*;

// FIXME(https://github.com/rust-lang/rust/issues/54140): Some errors could be
// made better if we could add multiple lines of error output like this:
//
// error: unsupported representation
//   --> enum.rs:28:8
//    |
// 28 | #[repr(transparent)]
//    |
// help: required by the derive of FromBytes
//
// Instead, we have more verbose error messages like "unsupported representation
// for deriving FromZeros, FromBytes, IntoBytes, or Unaligned on an enum"
//
// This will probably require Span::error
// (https://doc.rust-lang.org/nightly/proc_macro/struct.Span.html#method.error),
// which is currently unstable. Revisit this once it's stable.

/// Defines a derive function named `$outer` which parses its input
/// `TokenStream` as a `DeriveInput` and then invokes the `$inner` function.
///
/// Note that the separate `$outer` parameter is required - proc macro functions
/// are currently required to live at the crate root, and so the caller must
/// specify the name in order to avoid name collisions.
macro_rules! derive {
    ($trait:ident => $outer:ident => $inner:path) => {
        #[proc_macro_derive($trait, attributes(zerocopy))]
        pub fn $outer(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
            let ast = syn::parse_macro_input!(ts as DeriveInput);
            let ctx = match Ctx::try_from_derive_input(ast) {
                Ok(ctx) => ctx,
                Err(e) => return e.into_compile_error().into(),
            };
            let ts = $inner(&ctx, Trait::$trait).into_ts();
            // We wrap in `const_block` as a backstop in case any derive fails
            // to wrap its output in `const_block` (and thus fails to annotate)
            // with the full set of `#[allow(...)]` attributes).
            let ts = const_block([Some(ts)]);
            #[cfg(test)]
            crate::util::testutil::check_hygiene(ts.clone());
            ts.into()
        }
    };
}

trait IntoTokenStream {
    fn into_ts(self) -> proc_macro2::TokenStream;
}

impl IntoTokenStream for proc_macro2::TokenStream {
    fn into_ts(self) -> proc_macro2::TokenStream {
        self
    }
}

impl IntoTokenStream for Result<proc_macro2::TokenStream, Error> {
    fn into_ts(self) -> proc_macro2::TokenStream {
        match self {
            Ok(ts) => ts,
            Err(err) => err.to_compile_error(),
        }
    }
}

derive!(KnownLayout => derive_known_layout => crate::derive::known_layout::derive);
derive!(Immutable => derive_immutable => crate::derive::derive_immutable);
derive!(TryFromBytes => derive_try_from_bytes => crate::derive::try_from_bytes::derive_try_from_bytes);
derive!(FromZeros => derive_from_zeros => crate::derive::from_bytes::derive_from_zeros);
derive!(FromBytes => derive_from_bytes => crate::derive::from_bytes::derive_from_bytes);
derive!(IntoBytes => derive_into_bytes => crate::derive::into_bytes::derive_into_bytes);
derive!(Unaligned => derive_unaligned => crate::derive::unaligned::derive_unaligned);
derive!(ByteHash => derive_hash => crate::derive::derive_hash);
derive!(ByteEq => derive_eq => crate::derive::derive_eq);
derive!(SplitAt => derive_split_at => crate::derive::derive_split_at);

#[cfg_attr(not(zerocopy_unstable_linux), doc(hidden))]
#[proc_macro_derive(most_traits, attributes(zerocopy))]
pub fn most_traits(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast = syn::parse_macro_input!(ts as DeriveInput);
    let ctx = match Ctx::try_from_derive_input(ast) {
        Ok(ctx) => ctx,
        Err(e) => return e.into_compile_error().into(),
    }
    .skip_on_error();

    // top-level traits for which to attempt a derive
    let derives: [(fn(&Ctx, Trait) -> _, _); 6] = [
        (crate::derive::known_layout::derive, Trait::KnownLayout),
        (crate::derive::derive_immutable, Trait::Immutable),
        (crate::derive::from_bytes::derive_from_bytes, Trait::FromBytes),
        (crate::derive::into_bytes::derive_into_bytes, Trait::IntoBytes),
        (crate::derive::derive_split_at, Trait::SplitAt),
        (crate::derive::unaligned::derive_unaligned, Trait::Unaligned),
    ];

    let mut tokens = proc_macro2::TokenStream::new();
    for (derive, t) in derives {
        tokens.extend(derive(&ctx, t))
    }

    // We wrap in `const_block` as a backstop in case any derive fails
    // to wrap its output in `const_block` (and thus fails to annotate)
    // with the full set of `#[allow(...)]` attributes).
    let ts = const_block([Some(tokens)]);
    #[cfg(test)]
    crate::util::testutil::check_hygiene(ts.clone());
    ts.into()
}

/// Deprecated: prefer [`FromZeros`] instead.
#[deprecated(since = "0.8.0", note = "`FromZeroes` was renamed to `FromZeros`")]
#[doc(hidden)]
#[proc_macro_derive(FromZeroes)]
pub fn derive_from_zeroes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
    derive_from_zeros(ts)
}

/// Deprecated: prefer [`IntoBytes`] instead.
#[deprecated(since = "0.8.0", note = "`AsBytes` was renamed to `IntoBytes`")]
#[doc(hidden)]
#[proc_macro_derive(AsBytes)]
pub fn derive_as_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
    derive_into_bytes(ts)
}
