rustler/wrapper/
term.rs

1use crate::sys::{c_char, enif_snprintf};
2use crate::wrapper::NIF_TERM;
3use std::fmt;
4
5pub fn fmt(term: NIF_TERM, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
6    const SIZE: usize = 1024;
7    let mut bytes: Vec<u8> = Vec::with_capacity(SIZE);
8
9    let mut n = 0;
10    for _ in 0..10 {
11        let i = unsafe {
12            enif_snprintf!(
13                bytes.as_mut_ptr() as *mut c_char,
14                bytes.capacity(),
15                b"%T\x00" as *const u8 as *const c_char,
16                term
17            )
18        };
19        if i < 0 {
20            // Do not propagate an error, because string formatting is
21            // supposed to be infallible.
22            break;
23        }
24
25        n = i as usize;
26        if n >= bytes.capacity() {
27            // Bizarrely, enif_snprintf consistently underestimates the
28            // amount of memory it will need to write long lists. To try to
29            // avoid going around the loop again, double the estimate.
30            bytes.reserve_exact(2 * n + 1);
31
32            // Ensure that the `set_len` call below does not expose
33            // uninitialized bytes if we give up after 10 attempts.
34            n = 0;
35        } else {
36            break;
37        }
38    }
39
40    unsafe {
41        bytes.set_len(n);
42    }
43    f.write_str(&String::from_utf8_lossy(&bytes))
44}