I think it is a common task to manipulate file names and paths to append numbers or extra extensions, etc. I have encountered this problem myself a few times, and also found this post on StackOverflow about the issue.
From code I've seen, the commonly used solution is to use format! with .to_str().unwrap() on the path's parts. This is understandable, because format! won't work directly on &OsStr. Such pattern probably makes a lot of rust code break when used with invalid UTF-8 paths.
I myself try to avoid calling .to_str() on OsStr, and I usually .clone()/.to_owned(), then append the modifications in-place with .push(), which is much more cumbersome and uglier.
I think there should be in std a format-like macro that can format both Display and AsRef<OsStr>, but outputs OsString instead of String, thus providing a little friendlier experience with OsStr and Path.
There’s a Write impl so it should be possible to use the write! macro with it. Then it should be trivial to write a wrapper macro that creates an empty OsString and write!s the provided arguments to it.
Ah, but that doesn’t handle formatting in OsStr’s.
While formatting with/into bytestrings instead of utf8strings is certainly useful, it's not of any real help for OS strings, since those are (currently[1]) (mostly[2]) opaque and non introspectable.
Thus the only way the format_bytes crate is relevant is in that it's another crate which has implemented a custom format_args![3] macro.
There's been some talk of allowing bytewise views more widely (i.e. specifying the use of WTF-8 or OMG-WTF-8 on Windows). ↩︎
Unixy platforms have to/from bytes conversions via OsStrExt and it's known guaranteed that OS strings' encoding is a superset of UTF-8 because of the provided by-ref conversions between str and OsStr. ↩︎
Yes, technically they implemented a write!, not a format_args!. Morally, though, write!($w, $($args)*) is just $w.write_fmt(format_args!($($args)*)). ↩︎