//! # Rust bindings for NGINX
//!
//! The `ngx` crate provides a high-level Rust interface for the [NGINX] C APIs,
//! allowing creation of NGINX dynamic modules completely in Rust.
//!
//! [NGINX]: https://nginx.org/
//!
//! ## Project status
//!
//! This project is in active development. It is stable enough to be used in our
//! own products, but the APIs are not stabilized and breaking changes are expected.
//!
//! ## Build
//!
//! NGINX modules can be built against a particular version of NGINX. The following
//! environment variables can be used to specify the NGINX build to use:
//!
//! - `NGINX_BUILD_DIR` - absolute path to the NGINX build directory.
//!   Usually it's `objs` under the source directory, but can be changed with the
//!   `--builddir=` argument of the configure script.
//!
//! - `NGINX_SOURCE_DIR` - absolute path to the NGINX source directory, configured
//!   with the [`configure`](https://nginx.org/en/docs/configure.html) command.
//!
//! Only the `./configure` step of the NGINX build is mandatory because bindings
//! generator don't depend on any of the artifacts generated by `make`.
//!
//! For example, this is how you would compile the [examples](#examples) using a
//! specific version of NGINX:
//!
//! ```sh
//! NGINX_BUILD_DIR=/path/to/nginx-1.28.0/objs cargo build --package=examples --examples
//! ```
//!
//! ### Building with the NGINX build script
//!
//! You can build your Rust-based module as a part of the NGINX build process by
//! providing a `config` script implementation and passing the `--add-module`/
//! `--add-dynamic-module` options to the configure script.
//!
//! See the following example integration scripts: [`examples/config`] and
//! [`examples/config.make`].
//!
//! [`examples/config`]: https://github.com/bavshin-f5/ngx-rust/blob/main/examples/config
//! [`examples/config.make`]: https://github.com/bavshin-f5/ngx-rust/blob/main/examples/config.make
//!
//! ### Building with vendored NGINX sources
//!
//! It is possible to build module with a vendored copy of the NGINX sources
//! provided in the `nginx-src` crate by enabling feature `vendored`:
//!
//! By default, this will use the latest stable release of NGINX and require
//! system-wide installation of build dependencies (OpenSSL, PCRE2, Zlib).
//!
//! The behavior of vendored builds can be customized with environment variables,
//! as documented in the [nginx-src] crate README.
//!
//! **NOTE**: We recommend to build the module binaries against the exact source and
//! configuration of the NGINX build that you are planning to use in production,
//! and that is unlikely to be possible with the vendored source.
//!
//! `configure` arguments alter the APIs and the symbols visible to the Rust code,
//! and some OS distributions are known to ship nginx packages with API-breaking
//! patches applied.
//!
//! [nginx-src]: https://docs.rs/nginx-src/
//!
//! ## Cargo features
//!
//! - `alloc` - **Enabled** by default. This provides APIs that require allocations
//!   via the `alloc` crate.
//! - `async` - Enables a minimal async runtime built on top of the NGINX event loop.
//! - `serde` - Enables serialization support for some of the provided and
//!   re-exported types.
//! - `std` - **Enabled** by default. This provides APIs that require the standard
//!   library.
//! - `vendored`: Enables the build scripts to build a copy of nginx source and link
//!   against it. See the [nginx-src] crate documentation for additional details.
//!
//! ## Dependencies
//!
//! The following dependencies are required to build a Rust NGINX module on Linux
//! or BSD platform:
//!
//! - NGINX build dependencies: C compiler, make, OpenSSL, PCRE2, and Zlib.
//! - Rust toolchain (1.81.0 or later)
//! - [libclang] for rust-bindgen
//!
//! The installation process and the package names are system-dependent. Please,
//! consult the documentation for your distribution.
//!
//! Note that on some systems you will need `-devel` or `-dev` versions of the
//! packages.
//!
//! For example, [Dockerfile] contains the installation commands for Debian Linux.
//!
//! [Dockerfile]: https://github.com/nginx/ngx-rust/blob/main/Dockerfile
//! [libclang]: https://rust-lang.github.io/rust-bindgen/requirements.html
//!
//! ### macOS dependencies
//!
//! In order to use the optional GNU make build process on macOS, you will need
//! to install additional tools. This can be done via [homebrew](https://brew.sh/)
//! with the following command:
//!
//! ```sh
//! brew install make openssl grep
//! ```
//!
//! Additionally, you may need to set up LLVM and clang. Typically, this is done
//! as follows:
//!
//! ```sh
//! # make sure xcode tools are installed
//! xcode-select --install
//! # instal llvm
//! brew install --with-toolchain llvm
//! ```
#![warn(missing_docs)]
#![no_std]
#[cfg(feature = "alloc")]
extern crate alloc;

pub mod allocator;
#[cfg(feature = "async")]
pub mod async_;
pub mod collections;

/// The core module.
///
/// This module provides fundamental utilities needed to interface with many NGINX primitives.
/// String conversions, the pool (memory interface) object, and buffer APIs are covered here. These
/// utilities will generally align with the NGINX 'core' files and APIs.
pub mod core;

/// The ffi module.
///
/// This module provides scoped FFI bindings for NGINX symbols.
pub mod ffi;

/// The http module.
///
/// This modules provides wrappers and utilities to NGINX http APIs, such as requests,
/// configuration access, and statuses.
pub mod http;

/// The log module.
///
/// This module provides an interface into the NGINX logger framework.
pub mod log;

pub mod sync;

/// Define modules exported by this library.
///
/// These are normally generated by the Nginx module system, but need to be
/// defined when building modules outside of it.
#[macro_export]
macro_rules! ngx_modules {
    ($( $mod:ident ),+) => {
        #[no_mangle]
        #[allow(non_upper_case_globals)]
        pub static mut ngx_modules: [*const $crate::ffi::ngx_module_t; $crate::count!($( $mod, )+) + 1] = [
            $( unsafe { &$mod } as *const $crate::ffi::ngx_module_t, )+
            ::core::ptr::null()
        ];

        #[no_mangle]
        #[allow(non_upper_case_globals)]
        pub static mut ngx_module_names: [*const ::core::ffi::c_char; $crate::count!($( $mod, )+) + 1] = [
            $( concat!(stringify!($mod), "\0").as_ptr() as *const ::core::ffi::c_char, )+
            ::core::ptr::null()
        ];

        #[no_mangle]
        #[allow(non_upper_case_globals)]
        pub static mut ngx_module_order: [*const ::core::ffi::c_char; 1] = [
            ::core::ptr::null()
        ];
    };
}

/// Count number of arguments
#[macro_export]
macro_rules! count {
    () => { 0usize };
    ($x:tt, $( $xs:tt ),*) => { 1usize + $crate::count!($( $xs, )*) };
}
