Building up `PathBuf`s without intermediate allocating

Normally when I want to build a string without allocating I would use fmt::Write or associated macros. Since fmt::Write is not implemented for PathBuf, how do I build up paths without allocating unnecessary buffers.

Motivating example: I want to create files at /my/path/to/dir/<uuid>.<appropriate-extension>.

If you know the path in question is valid UTF-8, you can use format! to produce a String and then use PathBuf's From<String> impl -- which is documented as not allocating or copying memory. So:

let path_buf = PathBuf::from(format!("/my/path/to/{}.{}", uuid, ext));

The push method is also useful.

3 Likes

Alternatively if you don't want to guarantee the path is valid utf-8, you could have a string you use for building the filename of the path. You can fill this string with fmt::Write normally and push it to the PathBuf. By reusing this string, you can get away with one extra buffer.

This satisfies your requirement against unnecessary buffers as that's a plural, and my solution has only one extra buffer :slight_smile:

3 Likes

Thanks all for the help!

Here's another option:

fn path(dir: &OsStr, base: &OsStr, ext: &OsStr) -> PathBuf {
    let len = dir.len() + 1 + base.len() + 1 + ext.len();
    let mut buf = PathBuf::from(OsString::with_capacity(len));
    buf.push(dir);
    buf.push(base);
    buf.set_extension(ext);
    buf
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.