1extern crate libc;
4
5use libc::size_t;
6use std::io::Error;
7use std::os::raw::*;
8
9pub type Result<T> = ::std::result::Result<T, Error>;
11
12pub unsafe fn vsprintf<V>(format: *const c_char, va_list: *mut V) -> Result<String> {
14 vsprintf_raw(format, va_list)
15 .map(|bytes| String::from_utf8(bytes).expect("vsprintf result is not valid utf-8"))
16}
17
18pub unsafe fn vsprintf_raw<V>(format: *const c_char, va_list: *mut V) -> Result<Vec<u8>> {
21 let list_ptr = va_list as *mut c_void;
22
23 let mut buffer: Vec<u8> = Vec::new();
24 loop {
25 let rv = vsnprintf_wrapper(buffer.as_mut_ptr(), buffer.len(), format, list_ptr);
26
27 let character_count = if rv < 0 {
29 return Err(Error::last_os_error());
34 } else {
35 rv as usize
36 };
37
38 if character_count >= buffer.len() {
39 let new_len = character_count + 1;
40 buffer.reserve_exact(new_len - buffer.len());
41 buffer.set_len(new_len);
43 continue;
44 }
45
46 buffer.truncate(character_count);
48 break;
49 }
50
51 Ok(buffer)
52}
53
54extern "C" {
55 fn vsnprintf_wrapper(
56 buffer: *mut u8,
57 size: size_t,
58 format: *const c_char,
59 va_list: *mut c_void,
60 ) -> libc::c_int;
61}