changeset 180:a1bb1d013567

Remove `syn` from the dependency tree by implementing our own num_enum.
author Paul Fisher <paul@pfish.zone>
date Wed, 30 Jul 2025 18:22:16 -0400
parents dba9c1f40883
children a8c814843ccb
files Cargo.lock Cargo.toml src/constants.rs src/libpam/handle.rs src/libpam/items.rs src/libpam/memory.rs src/libpam/question.rs
diffstat 7 files changed, 110 insertions(+), 151 deletions(-) [+]
line wrap: on
line diff
--- a/Cargo.lock	Wed Jul 30 18:07:51 2025 -0400
+++ b/Cargo.lock	Wed Jul 30 18:22:16 2025 -0400
@@ -27,28 +27,6 @@
 ]
 
 [[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "hashbrown"
-version = "0.15.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
-
-[[package]]
-name = "indexmap"
-version = "2.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
-dependencies = [
- "equivalent",
- "hashbrown",
-]
-
-[[package]]
 name = "itoa"
 version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -98,7 +76,6 @@
  "libpam-sys",
  "libpam-sys-helpers",
  "libpam-sys-impls",
- "num_enum",
 ]
 
 [[package]]
@@ -113,37 +90,6 @@
 ]
 
 [[package]]
-name = "num_enum"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
-dependencies = [
- "num_enum_derive",
- "rustversion",
-]
-
-[[package]]
-name = "num_enum_derive"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "proc-macro-crate"
-version = "3.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
-dependencies = [
- "toml_edit",
-]
-
-[[package]]
 name = "proc-macro2"
 version = "1.0.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -162,12 +108,6 @@
 ]
 
 [[package]]
-name = "rustversion"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
-
-[[package]]
 name = "ryu"
 version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -274,33 +214,7 @@
 ]
 
 [[package]]
-name = "toml_datetime"
-version = "0.6.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
-
-[[package]]
-name = "toml_edit"
-version = "0.22.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
-dependencies = [
- "indexmap",
- "toml_datetime",
- "winnow",
-]
-
-[[package]]
 name = "unicode-ident"
 version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
-
-[[package]]
-name = "winnow"
-version = "0.7.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
-dependencies = [
- "memchr",
-]
--- a/Cargo.toml	Wed Jul 30 18:07:51 2025 -0400
+++ b/Cargo.toml	Wed Jul 30 18:22:16 2025 -0400
@@ -45,7 +45,6 @@
 [dependencies]
 bitflags = "2.9.0"
 libc = { optional = true, version = "0.2" }
-num_enum = "0.7.3"
 libpam-sys = { optional = true, path = "libpam-sys" }
 libpam-sys-helpers = { optional = true, path = "libpam-sys/libpam-sys-helpers" }
 libpam-sys-impls = { path = "libpam-sys/libpam-sys-impls" }
--- a/src/constants.rs	Wed Jul 30 18:07:51 2025 -0400
+++ b/src/constants.rs	Wed Jul 30 18:22:16 2025 -0400
@@ -407,10 +407,12 @@
 
 #[cfg(feature = "link")]
 impl ErrorCode {
+    /// Returned when an invalid constant is used.
     #[cfg(feature = "openpam-ext")]
-    const BAD_CONST: ErrorCode = ErrorCode::BadConstant;
+    pub const BAD_CONST: ErrorCode = ErrorCode::BadConstant;
+    /// Returned when an invalid constant is used.
     #[cfg(not(feature = "openpam-ext"))]
-    const BAD_CONST: ErrorCode = ErrorCode::SystemError;
+    pub const BAD_CONST: ErrorCode = ErrorCode::SystemError;
 
     pub(crate) fn result_from(ret: i32) -> Result<()> {
         match ret {
--- a/src/libpam/handle.rs	Wed Jul 30 18:07:51 2025 -0400
+++ b/src/libpam/handle.rs	Wed Jul 30 18:22:16 2025 -0400
@@ -6,11 +6,10 @@
 use crate::handle::PamShared;
 use crate::items::{Items, ItemsMut};
 use crate::libpam::environ::{LibPamEnviron, LibPamEnvironMut};
-use crate::libpam::items::{LibPamItems, LibPamItemsMut};
+use crate::libpam::items::{ItemType, LibPamItems, LibPamItemsMut};
 use crate::libpam::{items, memory};
 use crate::logging::{Level, Location, Logger};
 use crate::{AuthnFlags, AuthtokFlags, Conversation, EnvironMap, ModuleClient, Transaction};
-use num_enum::{IntoPrimitive, TryFromPrimitive};
 use std::any::TypeId;
 use std::cell::Cell;
 use std::ffi::{c_char, c_int, c_void, CString, OsStr, OsString};
@@ -524,40 +523,3 @@
     }
 }
 
-/// Identifies what is being gotten or set with `pam_get_item`
-/// or `pam_set_item`.
-#[derive(Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
-#[repr(i32)]
-#[non_exhaustive] // because C could give us anything!
-pub enum ItemType {
-    /// The PAM service name.
-    Service = libpam_sys::PAM_SERVICE,
-    /// The user's login name.
-    User = libpam_sys::PAM_USER,
-    /// The TTY name.
-    Tty = libpam_sys::PAM_TTY,
-    /// The remote host (if applicable).
-    RemoteHost = libpam_sys::PAM_RHOST,
-    /// The conversation struct (not a CStr-based item).
-    Conversation = libpam_sys::PAM_CONV,
-    /// The authentication token (password).
-    AuthTok = libpam_sys::PAM_AUTHTOK,
-    /// The old authentication token (when changing passwords).
-    OldAuthTok = libpam_sys::PAM_OLDAUTHTOK,
-    /// The remote user's name.
-    RemoteUser = libpam_sys::PAM_RUSER,
-    /// The prompt shown when requesting a username.
-    UserPrompt = libpam_sys::PAM_USER_PROMPT,
-    #[cfg(feature = "linux-pam-ext")]
-    /// App-supplied function to override failure delays.
-    FailDelay = libpam_sys::PAM_FAIL_DELAY,
-    #[cfg(feature = "linux-pam-ext")]
-    /// X display name.
-    XDisplay = libpam_sys::PAM_XDISPLAY,
-    #[cfg(feature = "linux-pam-ext")]
-    /// X server authentication data.
-    XAuthData = libpam_sys::PAM_XAUTHDATA,
-    #[cfg(feature = "linux-pam-ext")]
-    /// The type of `pam_get_authtok`.
-    AuthTokType = libpam_sys::PAM_AUTHTOK_TYPE,
-}
--- a/src/libpam/items.rs	Wed Jul 30 18:07:51 2025 -0400
+++ b/src/libpam/items.rs	Wed Jul 30 18:22:16 2025 -0400
@@ -1,12 +1,49 @@
 use crate::constants::ErrorCode;
 use crate::constants::Result;
 use crate::items::{Items, ItemsMut};
-use crate::libpam::handle::ItemType;
 use crate::libpam::handle::LibPamHandle;
 use crate::libpam::memory;
 use std::ffi::{c_int, OsStr, OsString};
 use std::ptr;
 
+memory::num_enum! {
+    /// Identifies what is being gotten or set with `pam_get_item`
+    /// or `pam_set_item`.
+    #[non_exhaustive]
+    pub enum ItemType(i32) {
+        /// The PAM service name.
+        Service = libpam_sys::PAM_SERVICE,
+        /// The user's login name.
+        User = libpam_sys::PAM_USER,
+        /// The TTY name.
+        Tty = libpam_sys::PAM_TTY,
+        /// The remote host (if applicable).
+        RemoteHost = libpam_sys::PAM_RHOST,
+        /// The conversation struct (not a CStr-based item).
+        Conversation = libpam_sys::PAM_CONV,
+        /// The authentication token (password).
+        AuthTok = libpam_sys::PAM_AUTHTOK,
+        /// The old authentication token (when changing passwords).
+        OldAuthTok = libpam_sys::PAM_OLDAUTHTOK,
+        /// The remote user's name.
+        RemoteUser = libpam_sys::PAM_RUSER,
+        /// The prompt shown when requesting a username.
+        UserPrompt = libpam_sys::PAM_USER_PROMPT,
+        #[cfg(feature = "linux-pam-ext")]
+        /// App-supplied function to override failure delays.
+        FailDelay = libpam_sys::PAM_FAIL_DELAY,
+        #[cfg(feature = "linux-pam-ext")]
+        /// X display name.
+        XDisplay = libpam_sys::PAM_XDISPLAY,
+        #[cfg(feature = "linux-pam-ext")]
+        /// X server authentication data.
+        XAuthData = libpam_sys::PAM_XAUTHDATA,
+        #[cfg(feature = "linux-pam-ext")]
+        /// The type of `pam_get_authtok`.
+        AuthTokType = libpam_sys::PAM_AUTHTOK_TYPE,
+    }
+}
+
 pub struct LibPamItems<'a>(pub &'a LibPamHandle);
 pub struct LibPamItemsMut<'a>(pub &'a mut LibPamHandle);
 
--- a/src/libpam/memory.rs	Wed Jul 30 18:07:51 2025 -0400
+++ b/src/libpam/memory.rs	Wed Jul 30 18:22:16 2025 -0400
@@ -9,6 +9,52 @@
 use std::ptr::NonNull;
 use std::{mem, ptr, slice};
 
+/// Like the num_enum crate, but with no dependency on `syn`.
+macro_rules! num_enum {
+    (
+        $(#[$m:meta])*
+        $viz:vis enum $name:ident($repr:ty) {
+            $(
+                $(#[$im:meta])*
+                $item_name:ident = $item_value:path,
+            )*
+        }
+    ) => {
+        $(#[$m])*
+        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+        #[repr($repr)]
+        $viz enum $name {
+            $(
+                $(#[$im])*
+                $item_name = $item_value,
+            )*
+        }
+
+        impl TryFrom<$repr> for $name {
+            type Error = crate::constants::ErrorCode;
+
+            #[allow(unused_doc_comments)]
+            fn try_from(value: $repr) -> crate::constants::Result<$name> {
+                match value {
+                    $(
+                        $(#[$im])*
+                        $item_value => Ok(Self::$item_name),
+                    )*
+                    _ => Err(crate::constants::ErrorCode::BAD_CONST),
+                }
+            }
+        }
+
+        impl From<$name> for $repr {
+            fn from(value: $name) -> $repr {
+                value as $repr
+            }
+        }
+    }
+}
+
+pub(crate) use num_enum;
+
 /// Allocates `count` elements to hold `T`.
 #[inline]
 pub fn calloc<T>(count: usize) -> NonNull<T> {
--- a/src/libpam/question.rs	Wed Jul 30 18:07:51 2025 -0400
+++ b/src/libpam/question.rs	Wed Jul 30 18:22:16 2025 -0400
@@ -6,32 +6,31 @@
 use crate::ErrorCode;
 use crate::Result;
 use libpam_sys_helpers;
-use num_enum::{IntoPrimitive, TryFromPrimitive};
 use std::ffi::{c_int, c_void, CStr, OsStr};
 use std::os::unix::ffi::OsStrExt;
 use std::ptr::NonNull;
 
-/// The C enum values for messages shown to the user.
-#[derive(Debug, PartialEq, TryFromPrimitive, IntoPrimitive)]
-#[repr(i32)]
-enum Style {
-    /// Requests information from the user; will be masked when typing.
-    PromptEchoOff = libpam_sys::PAM_PROMPT_ECHO_OFF,
-    /// Requests information from the user; will not be masked.
-    PromptEchoOn = libpam_sys::PAM_PROMPT_ECHO_ON,
-    /// An error message.
-    ErrorMsg = libpam_sys::PAM_ERROR_MSG,
-    /// An informational message.
-    TextInfo = libpam_sys::PAM_TEXT_INFO,
-    /// Yes/No/Maybe conditionals. A Linux-PAM extension.
-    #[cfg(feature = "linux-pam-ext")]
-    RadioType = libpam_sys::PAM_RADIO_TYPE,
-    /// For server–client non-human interaction.
-    ///
-    /// NOT part of the X/Open PAM specification.
-    /// A Linux-PAM extension.
-    #[cfg(feature = "linux-pam-ext")]
-    BinaryPrompt = libpam_sys::PAM_BINARY_PROMPT,
+memory::num_enum! {
+    /// The C enum values for messages shown to the user.
+    enum Style(i32) {
+        /// Requests information from the user; will be masked when typing.
+        PromptEchoOff = libpam_sys::PAM_PROMPT_ECHO_OFF,
+        /// Requests information from the user; will not be masked.
+        PromptEchoOn = libpam_sys::PAM_PROMPT_ECHO_ON,
+        /// An error message.
+        ErrorMsg = libpam_sys::PAM_ERROR_MSG,
+        /// An informational message.
+        TextInfo = libpam_sys::PAM_TEXT_INFO,
+        /// Yes/No/Maybe conditionals. A Linux-PAM extension.
+        #[cfg(feature = "linux-pam-ext")]
+        RadioType = libpam_sys::PAM_RADIO_TYPE,
+        /// For server–client non-human interaction.
+        ///
+        /// NOT part of the X/Open PAM specification.
+        /// A Linux-PAM extension.
+        #[cfg(feature = "linux-pam-ext")]
+        BinaryPrompt = libpam_sys::PAM_BINARY_PROMPT,
+    }
 }
 
 /// A question sent by PAM or a module to an application.