libedit-sys 0.3.0

Low-level FFI bindings to the libedit line-editing library
Documentation
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#![allow(unknown_lints)]
#![allow(unnecessary_transmutes)]
#![allow(clippy::all)]

//! Low-level FFI bindings to the [libedit](https://www.thrysoee.dk/editline/)
//! line-editing library (also known as editline, the BSD alternative to GNU
//! readline).
//!
//! These are **raw, unsafe** bindings generated by bindgen. They provide
//! direct access to the C API with no ergonomic wrappers.
//!
//! # Variadic functions
//!
//! Several core functions are C variadic (`el_set`, `el_get`, `el_wset`,
//! `el_wget`, `history`, `history_w`). Calling C variadic functions from
//! Rust is **undefined behavior** and may silently corrupt data.
//!
//! *Simple integer/pointer arguments often work by accident*, but this is
//! not guaranteed across platforms or compiler versions. To safely use the
//! full libedit API, you have two options:
//!
//! 1. Write a small C shim that wraps specific variadic call patterns
//!    with fixed-argument functions.
//!
//! 2. Use the companion [`libedit`](https://crates.io/crates/libedit)
//!    crate, which provides safe wrappers and includes the necessary C shim.
//!
//! This crate intentionally keeps the raw variadic bindings available so
//! advanced users are not restricted, but they are **use at your own risk**.

// When the `bindgen` feature is enabled, use freshly generated bindings.
// Otherwise, use the pre-generated bindings shipped with the crate
// (platform-specific: macOS ships an older libedit with fewer symbols).
#[cfg(feature = "bindgen")]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

#[cfg(all(not(feature = "bindgen"), target_os = "macos"))]
include!("bindings-macos.rs");

#[cfg(all(not(feature = "bindgen"), not(target_os = "macos")))]
include!("bindings.rs");

// Safety assertions at compile time
#[cfg(test)]
mod tests {
    use super::*;
    use std::mem;

    #[test]
    fn test_editline_type_sizes() {
        // EditLine, History, and Tokenizer are opaque pointers -- verify they compile
        assert_eq!(mem::size_of::<*const EditLine>(), mem::size_of::<usize>());
        assert_eq!(mem::size_of::<*const History>(), mem::size_of::<usize>());
        assert_eq!(mem::size_of::<*const Tokenizer>(), mem::size_of::<usize>());
    }

    #[test]
    fn test_file_used_only_behind_pointer() {
        // `FILE` is deliberately an opaque, zero-sized type: libedit and this
        // crate only ever use it as `*mut FILE`. A pointer to it must be a
        // single machine word regardless of what libc's real `FILE` size is
        // on the target platform. This locks in the "only used behind a
        // pointer" contract so a future change that relies on the pointee's
        // size (which would be platform-specific and unsound) can't slip in
        // unnoticed.
        assert_eq!(mem::size_of::<*mut FILE>(), mem::size_of::<usize>());
        assert_eq!(
            mem::size_of::<FILE>(),
            0,
            "FILE must remain zero-sized/opaque"
        );
    }

    #[test]
    fn test_hist_event() {
        // HistEvent is a concrete struct, verify it exists
        let _event: HistEvent = unsafe { mem::zeroed() };
    }
}