view libpam-sys/libpam-sys-helpers/src/pam_impl.rs @ 141:a508a69c068a

Remove a lot of Results from functions. Many functions are documented to only return failing Results when given improper inputs or when there is a memory allocation failure (which can be verified by looking at the source). In cases where we know our input is correct, we don't need to check for memory allocation errors for the same reason that Rust doesn't do so when you, e.g., create a new Vec.
author Paul Fisher <paul@pfish.zone>
date Sat, 05 Jul 2025 17:16:56 -0400
parents efbc235f01d3
children
line wrap: on
line source

// This file is include!d directly by `../build.rs`, so its doc comment
// is found in lib.rs.

/// An enum that knows its own values.
macro_rules! self_aware_enum {
    (
        $(#[$enumeta:meta])*
        $viz:vis enum $name:ident {
            $(
                $(#[$itemeta:meta])*
                $item:ident,
            )*
        }
    ) => {
        $(#[$enumeta])*
        $viz enum $name {
            $(
                $(#[$itemeta])*
                $item,
            )*
        }

        // The implementations in this block are private for now
        // to avoid putting a contract into the public API.
        #[allow(dead_code)]
        impl $name {
            /// Iterator over the items in the enum. For internal use.
            fn items() -> Vec<Self> {
                vec![$(Self::$item),*]
            }

            /// Attempts to parse the enum from the string. For internal use.
            fn try_from(value: &str) -> Result<Self, String> {
                match value {
                    $(stringify!($item) => Ok(Self::$item),)*
                    _ => Err(value.into()),
                }
            }
        }
    };
}

self_aware_enum! {
    /// The PAM implementations supported by `libpam-sys`.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    #[cfg_attr(pam_impl, non_exhaustive)]
    pub enum PamImpl {
        /// [Linux-PAM] is provided by most Linux distributions.
        ///
        /// [Linux-PAM]: https://github.com/linux-pam/linux-pam
        LinuxPam,
        /// [OpenPAM] is used by most BSDs, including Mac OS X.
        ///
        /// [OpenPAM]: https://git.des.dev/OpenPAM/OpenPAM
        OpenPam,
        /// Illumos and Solaris use a derivative of [Sun's implementation][sun].
        ///
        /// [sun]: https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/lib/libpam
        Sun,
        /// Only the functionality and constants in [the PAM spec].
        ///
        /// [the PAM spec]: https://pubs.opengroup.org/onlinepubs/8329799/toc.htm
        XSso,
    }
}

// This generated file contains:
// - pam_impl_name!
// - PamImpl::CURRENT
#[cfg(pam_impl)]
include!(concat!(env!("OUT_DIR"), "/pam_impl_const.rs"));

#[allow(clippy::needless_doctest_main)]
/// Generates `cargo` directives for build scripts to enable `cfg(pam_impl)`.
///
/// Print this in your `build.rs` script to be able to use the custom `pam_impl`
/// configuration directive.
///
/// ```
/// // build.rs
/// use libpam_sys_helpers::pam_impl;
/// fn main() {
///     pam_impl::enable_pam_impl_cfg();
///
///     // Whatever other stuff you do in your build.rs.
/// }
/// ```
#[cfg(pam_impl)]
pub fn enable_pam_impl_cfg() {
    println!("{}", pam_impl_cfg_string())
}

/// Generates the `cargo:` directives to print in build scripts.
#[cfg(pam_impl)]
pub fn pam_impl_cfg_string() -> String {
    generate_cfg(pam_impl_name!())
}

fn generate_cfg(name: &str) -> String {
    let impls: Vec<_> = PamImpl::items()
        .into_iter()
        .map(|i| format!(r#""{i:?}""#))
        .collect();
    format!(
        "\
cargo:rustc-check-cfg=cfg(pam_impl)
cargo:rustc-check-cfg=cfg(pam_impl, values({impls}))
cargo:rustc-cfg=pam_impl
cargo:rustc-cfg=pam_impl={name:?}
        ",
        impls = impls.join(",")
    )
}