Store or return strings consisting of multiple lines

I'm currently considering to redesign the sandkiste::errors module. In that context, I have also been looking at the sandkiste::errors::MachineError::machine_backtrace field, which is supposed to contain a string consisting of multiple lines.

I didn't specify yet whether there should be a trailing '\n' character included (or how lines are seperated at all, i.e. "\r\n" vs "\n" or maybe even other ways). In my mind, multi-line strings were always/implicitly containing a trailing new-line indicator, but now I have doubts.

My question is: what's the idiomatic way to store "several lines of Unicode strings" in Rust? Some ideas:

  • Use Vec<String>
  • Use a single String with
    • '\n' as line separator with trailing '\n' after the last line
    • '\n' as line separator without trailing '\n' after the last line
    • use the native line separator (e.g. "\r\n" on Windows), with or without adding a trailing separator after the last line
    • use U+2028 (I doubt that would be a good idea though), with or without trailing one

I noticed that anyhow does not emit a newline when requesting the (possible multi-line) debug output for an error, for example:

fn main() {
    let err = std::io::Error::new(std::io::ErrorKind::Other, "Dummy error");
    let err = anyhow::Error::from(err).context("Dummy context");
    println!("{err:?}(NO NEWLINE HERE){err:?}");



Dummy context

Caused by:
    Dummy error(NO NEWLINE HERE)Dummy context

Caused by:
    Dummy error

Unfortunately, std::fmt::Debug doesn't give any advice on that matter though. I feel like this is somehow underspecified, isn't it? Or is it deliberately left unspecified?

I found the thread Formatln! = format! + platform specific newline on IRLO. Considering that println! uses "\n" as line separator, regardless of the platform, I would stick to using it too.

Only question remains is the trailing newline: yes or no. I tend towards not using a trailing newline separator now. Apparently that's also what Lua's traceback does (used by sandkiste_lua).

But still curious about some opinions on that matter.

Apparently Lua uses "\r\n" though. This makes me wonder if I should normalize backtraces generated by Lua and remove the '\r' when creating a MachineError in Rust. :weary: