diff src/constants.rs @ 60:05cc2c27334f

The Big Refactor: clean up docs and exports. - Brings the most important symbols in the library to the root with `pub use` statements. - Expands and updates documentation. - Rearranges things extensively to make the external interface nicer and make the structure easier to understand. - Renames a few things (e.g. `Result`).
author Paul Fisher <paul@pfish.zone>
date Wed, 21 May 2025 19:00:51 -0400
parents 3f4a77aa88be
children a7aa5ca0d00d
line wrap: on
line diff
--- a/src/constants.rs	Wed May 21 00:27:18 2025 -0400
+++ b/src/constants.rs	Wed May 21 19:00:51 2025 -0400
@@ -1,24 +1,37 @@
+//! Constants and enum values from the PAM library.
+
 use bitflags::bitflags;
 use libc::{c_int, c_uint};
 use num_derive::FromPrimitive;
 use num_traits::FromPrimitive;
 use std::any;
 use std::marker::PhantomData;
-// TODO: Import constants from C header file at compile time.
 
-// The Linux-PAM flags
-// see /usr/include/security/_pam_types.h
 bitflags! {
+    /// The available PAM flags.
+    ///
+    /// See `/usr/include/security/_pam_types.h` for more details.
     #[derive(Debug, PartialEq)]
     #[repr(transparent)]
     pub struct Flags: c_uint {
+        /// Authentication service should not generate any messages.
         const SILENT = 0x8000;
+        /// The service should return [ErrorCode::AuthError] if the user
+        /// has a null authentication token.
         const DISALLOW_NULL_AUTHTOK = 0x0001;
+        /// Set user credentials for an authentication service.
         const ESTABLISH_CRED = 0x0002;
+        /// Delete user credentials associated with
+        /// an authentication service.
         const DELETE_CRED = 0x0004;
+        /// Reinitialize user credentials.
         const REINITIALIZE_CRED = 0x0008;
+        /// Extend the lifetime of user credentials.
         const REFRESH_CRED = 0x0010;
-        const CHANGE_EXPIRED_AUTHTOK= 0x0020;
+        /// The password service should only update those passwords
+        /// that have aged. If this flag is _not_ passed,
+        /// the password service should update all passwords.
+        const CHANGE_EXPIRED_AUTHTOK = 0x0020;
     }
 }
 
@@ -43,7 +56,7 @@
 
 impl TryFrom<c_int> for MessageStyle {
     type Error = InvalidEnum<Self>;
-    fn try_from(value: c_int) -> Result<Self, Self::Error> {
+    fn try_from(value: c_int) -> std::result::Result<Self, Self::Error> {
         Self::from_i32(value).ok_or(value.into())
     }
 }
@@ -54,8 +67,8 @@
     }
 }
 
-/// The Linux-PAM error return values.
-/// Success is instead represented by the `Ok` entry of a `Result`.
+/// The Linux-PAM error return values. Success is an Ok [Result].
+///
 /// Most abbreviations (except `AuthTok` and `Max`) are now full words.
 /// For more detailed information, see
 /// `/usr/include/security/_pam_types.h`.
@@ -127,19 +140,21 @@
     Incomplete = 31,
 }
 
-pub type PamResult<T> = Result<T, ErrorCode>;
+/// A PAM-specific Result type with an [ErrorCode] error.
+pub type Result<T> = std::result::Result<T, ErrorCode>;
+
 impl ErrorCode {
-    /// Converts a PamResult into the result code that C wants.
-    pub fn result_to_c(value: PamResult<()>) -> c_int {
+    /// Converts this [Result] into a C-compatible result code.
+    pub fn result_to_c<T>(value: Result<T>) -> c_int {
         match value {
             Ok(_) => 0, // PAM_SUCCESS
             Err(otherwise) => otherwise.into(),
         }
     }
 
-    /// Converts a C result code into a PamResult, with success as Ok.
+    /// Converts a C result code into a [Result], with success as Ok.
     /// Invalid values are returned as a [Self::SystemError].
-    pub fn result_from(value: c_int) -> PamResult<()> {
+    pub fn result_from(value: c_int) -> Result<()> {
         match value {
             0 => Ok(()),
             value => Err(value.try_into().unwrap_or(Self::SystemError)),
@@ -150,7 +165,7 @@
 impl TryFrom<c_int> for ErrorCode {
     type Error = InvalidEnum<Self>;
 
-    fn try_from(value: c_int) -> Result<Self, Self::Error> {
+    fn try_from(value: c_int) -> std::result::Result<Self, Self::Error> {
         Self::from_i32(value).ok_or(value.into())
     }
 }
@@ -163,12 +178,18 @@
 
 /// Error returned when attempting to coerce an invalid C integer into an enum.
 #[derive(thiserror::Error)]
-#[error("{} is not a valid {}", .0, any::type_name::<T>())]
+#[error("{0} is not a valid {type}", type = any::type_name::<T>())]
 #[derive(Debug, PartialEq)]
-pub struct InvalidEnum<T>(std::ffi::c_int, PhantomData<T>);
+pub struct InvalidEnum<T>(c_int, PhantomData<T>);
 
-impl<T> From<std::ffi::c_int> for InvalidEnum<T> {
-    fn from(value: std::ffi::c_int) -> Self {
+impl<T> From<InvalidEnum<T>> for c_int {
+    fn from(value: InvalidEnum<T>) -> Self {
+        value.0
+    }
+}
+
+impl<T> From<c_int> for InvalidEnum<T> {
+    fn from(value: c_int) -> Self {
         Self(value, PhantomData)
     }
 }
@@ -180,9 +201,12 @@
     #[test]
     fn test_enums() {
         assert_eq!(Ok(MessageStyle::ErrorMsg), 3.try_into());
-        assert_eq!(Err(999.into()), ErrorCode::try_from(999));
+        assert_eq!(Err(InvalidEnum::from(999)), ErrorCode::try_from(999));
         assert_eq!(Ok(()), ErrorCode::result_from(0));
         assert_eq!(Err(ErrorCode::Abort), ErrorCode::result_from(26));
         assert_eq!(Err(ErrorCode::SystemError), ErrorCode::result_from(423));
+        assert!(InvalidEnum::<MessageStyle>(33, PhantomData)
+            .to_string()
+            .starts_with("33 is not a valid "));
     }
 }