ext-php-rs 0.10.0

Bindings for the Zend API to build PHP extensions natively in Rust.
Documentation
//! Types and traits for registering constants in PHP.

use std::ffi::CString;

use super::flags::GlobalConstantFlags;
use crate::error::Result;
use crate::ffi::{
    zend_register_bool_constant, zend_register_double_constant, zend_register_long_constant,
    zend_register_string_constant,
};

/// Implemented on types which can be registered as a constant in PHP.
pub trait IntoConst: Sized {
    /// Registers a global module constant in PHP, with the value as the content
    /// of self. This function _must_ be called in the module startup
    /// function, which is called after the module is initialized. The
    /// second parameter of the startup function will be the module number.
    /// By default, the case-insensitive and persistent flags are set when
    /// registering the constant.
    ///
    /// Returns a result containing nothing if the constant was successfully
    /// registered.
    ///
    /// # Parameters
    ///
    /// * `name` - The name of the constant.
    /// * `module_number` - The module number that we are registering the
    ///   constant under.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ext_php_rs::constant::IntoConst;
    ///
    /// pub extern "C" fn startup_function(_type: i32, module_number: i32) -> i32 {
    ///     5.register_constant("MY_CONST_NAME", module_number); // MY_CONST_NAME == 5
    ///     "Hello, world!".register_constant("STRING_CONSTANT", module_number); // STRING_CONSTANT == "Hello, world!"
    ///     0
    /// }
    /// ```
    fn register_constant(&self, name: &str, module_number: i32) -> Result<()> {
        self.register_constant_flags(
            name,
            module_number,
            GlobalConstantFlags::CaseSensitive | GlobalConstantFlags::Persistent,
        )
    }

    /// Registers a global module constant in PHP, with the value as the content
    /// of self. This function _must_ be called in the module startup
    /// function, which is called after the module is initialized. The
    /// second parameter of the startup function will be the module number.
    /// This function allows you to pass any extra flags in if you require.
    /// Note that the case-sensitive and persistent flags *are not* set when you
    /// use this function, you must set these yourself.
    ///
    /// Returns a result containing nothing if the constant was successfully
    /// registered.
    ///
    /// # Parameters
    ///
    /// * `name` - The name of the constant.
    /// * `module_number` - The module number that we are registering the
    ///   constant under.
    /// * `flags` - Flags to register the constant with.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ext_php_rs::{constant::IntoConst, flags::GlobalConstantFlags};
    ///
    /// pub extern "C" fn startup_function(_type: i32, module_number: i32) -> i32 {
    ///     42.register_constant_flags("MY_CONST_NAME", module_number, GlobalConstantFlags::Persistent | GlobalConstantFlags::Deprecated);
    ///     0
    /// }
    /// ```
    fn register_constant_flags(
        &self,
        name: &str,
        module_number: i32,
        flags: GlobalConstantFlags,
    ) -> Result<()>;
}

impl IntoConst for String {
    fn register_constant_flags(
        &self,
        name: &str,
        module_number: i32,
        flags: GlobalConstantFlags,
    ) -> Result<()> {
        self.as_str()
            .register_constant_flags(name, module_number, flags)
    }
}

impl IntoConst for &str {
    fn register_constant_flags(
        &self,
        name: &str,
        module_number: i32,
        flags: GlobalConstantFlags,
    ) -> Result<()> {
        unsafe {
            zend_register_string_constant(
                CString::new(name)?.as_ptr(),
                name.len() as _,
                CString::new(*self)?.as_ptr(),
                flags.bits() as _,
                module_number,
            )
        };
        Ok(())
    }
}

impl IntoConst for bool {
    fn register_constant_flags(
        &self,
        name: &str,
        module_number: i32,
        flags: GlobalConstantFlags,
    ) -> Result<()> {
        unsafe {
            zend_register_bool_constant(
                CString::new(name)?.as_ptr(),
                name.len() as _,
                *self,
                flags.bits() as _,
                module_number,
            )
        };
        Ok(())
    }
}

/// Implements the `IntoConst` trait for a given number type using a given
/// function.
macro_rules! into_const_num {
    ($type: ty, $fn: expr) => {
        impl IntoConst for $type {
            fn register_constant_flags(
                &self,
                name: &str,
                module_number: i32,
                flags: GlobalConstantFlags,
            ) -> Result<()> {
                Ok(unsafe {
                    $fn(
                        CString::new(name)?.as_ptr(),
                        name.len() as _,
                        *self as _,
                        flags.bits() as _,
                        module_number,
                    )
                })
            }
        }
    };
}

into_const_num!(i8, zend_register_long_constant);
into_const_num!(i16, zend_register_long_constant);
into_const_num!(i32, zend_register_long_constant);
into_const_num!(i64, zend_register_long_constant);
into_const_num!(f32, zend_register_double_constant);
into_const_num!(f64, zend_register_double_constant);