What is the best practice to create a very complex string?

⚓ Rust    📅 2025-08-04    👤 surdeus    👁️ 10      

surdeus

Warning

This post was published 121 days ago. The information described in this article may have changed.

I'm trying to create a small program which translate excel file to html String.
I wrote a POC first, and suddenly realized that, I allocated unexpectedly many strings:

fn rendered<T: AsRef<Path>>(p: Result<T, String>) -> String {
    let p = match p {
        Ok(p) => p,
        Err(p) => return p,
    };
    let p = p.as_ref();
    let file_name = p.file_name();
    let p = fs::read(p).unwrap();
    let cursor = io::Cursor::new(p);
    let f = xlsx::read_reader(cursor, true).unwrap();
    return format!(
        "{file_name:?}\n{}",
        f.get_sheet_collection()
            .iter()
            .map(|x| get_sheet(x, f.get_theme()))
            .collect::<Vec<_>>()
            .join(",")
    );
}
// use umya_spreadsheet::structs::Worksheet;
fn get_sheet(x: &Worksheet, theme: &Theme) -> String {
    format!("{}\n{}", x.get_name(), get_content(x, theme))
}
fn get_content(x: &Worksheet, theme: &Theme) -> String {
    format!(
        r##"<table border="1px" style="text-align: center">{}</table>"##,
        (0..x.get_highest_row())
            .map(|idx| format!(
                r##"<tr>{}</tr>"##,
                get_cell_content(x.get_collection_by_row(&idx).into_iter(), theme)
            ))
            .collect::<Vec<_>>()
            .join("\n")
    )
}
fn get_cell_content<'a>(x: impl Iterator<Item = &'a Cell>, theme: &Theme) -> String {
    x.map(|x| {
        format!(
            r##"<td{}>{}</td>"##,
            if let Some(color) = x.get_style().get_background_color() {
                &format!(
                    r##" bgcolor="#{}""##,
                    if color.get_argb_with_theme(theme).len() == 8 {
                        color.get_argb_with_theme(theme)[2..].to_string()
                    } else {
                        color.get_argb_with_theme(theme).to_string()
                    }
                )
            } else {
                ""
            },
            x.get_formatted_value()
        )
    })
    .collect::<Vec<_>>()
    .join("")
}

I know 2 ways to avoid unnecessary allocations:
One of them is use fmt::Write, with either rewrite std::fmt::Display/Debug or just manually execute fmt::Write in the target string, which works but require lots of manual work.
Another of them is use format_args! macro, but this is limited to some simple expressions only.

I wonder is there any method I don't know, or is it worth to invent another method?

2 posts - 2 participants

Read full topic

🏷️ Rust_feed