Expand description

Types and functions for the safe use of printf(3)-style format strings.

printf(3) (POSIX, Linux, and FreeBSD man pages) and its variants present some challenges for memory-safe use from Rust: the passed-in arguments are interpreted as different types based on the content of the format string, with each conversion specification (e.g., %s) consuming up to three arguments (e.g, %*.*d), and the %n specification even writing to memory! For memory- and type-safe use, we must make sure a given format string is only used in invocations with the correct argument number and type.

This crate contains mechanisms you can use to ensure such agreement. PrintfFmt<(A, B, ...)> wraps a format string, doing verification to ensure it can be safely used with the list of arguments corresponding to the tuple of types (A: PrintfArgument, B: PrintfArgument, ...). This verification may be performed at compile time, allowing for safe wrappers with zero runtime overhead.

A brief example of how this crate might be used:

use printf_wrap::{PrintfFmt, PrintfArgument};
use libc::{c_int, printf};

/// Safe wrapper for calling printf with two value arguments.
pub fn printf_with_2_args<T, U>(fmt: PrintfFmt<(T, U)>, arg1: T, arg2: U) -> c_int
where
    T: PrintfArgument,
    U: PrintfArgument,
{
    unsafe { printf(fmt.as_ptr(), arg1.as_c_val(), arg2.as_c_val()) }
}

fn main() {
    const MY_FMT: PrintfFmt<(u32, i32)> =
        PrintfFmt::new_or_panic("unsigned = %u, signed = %d\0");
    printf_with_2_args(MY_FMT, 42, -7);
}

The example module has a more worked-out example of this crate’s use, using printf(3) and snprintf(3) as the functions to wrap.

Only a subset of all possible printf format strings are accepted:

  • Numbered argument conversion specifications (e.g., %2$d) are not supported.
  • %lc, %ls, %C, %S, and %L[fFeEgGaA] are not supported.
  • %n is not supported.

Modules

exampleexample

An example of how to use the types and traits of this crate to safely wrap functions with printf(3)-style format strings and varargs.

Macros

Convenience macro for creating a const NullString, including appending a null character.

Structs

A wrapper for a 'static null-terminated string.

A type-safe wrapper around a C-style string verified to be compatible with use as a format string for printf(3)-style functions called with T as the varargs.

Traits

Utility trait for determining which of two integer types is larger.

A list of Rust-side arguments to a printf(3)-style function.

A PrintfArgs in a form more amenable to recursive processing.

A Rust-side argument to a safe wrapper around a printf(3)-like function.

Functions

Returns whether fmt is (1) a valid C-style string and (2) a format string compatible with the tuple of arguments T when used in a printf(3)-like function.

Type Definitions

Type alias that better conveys LargerOfOp’s nature as a type-level function.