Repository: tokio-rs/axum
File: axum-extra/src/response/multiple.rs (Rust)

Code before:
            serialized_part += &format!("; filename=\"{}\"", filename);
        }
        serialized_part += "\r\n";
        // specify the MIME type
        serialized_part += &format!("Content-Type: {}\r\n", self.mime_type);
        serialized_part += "\r\n";
        let mut part_bytes = serialized_part.as_bytes().to_vec();
        part_bytes.extend_from_slice(&self.contents);
        part_bytes.extend_from_slice(b"\r\n");

        part_bytes
    }
}

impl FromIterator<Part> for MultipartForm {
    fn from_iter<T: IntoIterator<Item = Part>>(iter: T) -> Self {
        Self {
            parts: iter.into_iter().collect(),
        }
    }
}

/// A boundary is defined as a user defined (arbitrary) value that does not occur in any of the data.
/// Because the specification does not clearly define a methodology for generating boundaries, this implementation
/// follow's Reqwest's, and generates a boundary in the format of `XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX` where `XXXXXXXX`
/// is a hexadecimal representation of a pseudo randomly generated u64.
fn generate_boundary() -> String {
    let a = fastrand::u64(0..u64::MAX);
    let b = fastrand::u64(0..u64::MAX);
    let c = fastrand::u64(0..u64::MAX);
    let d = fastrand::u64(0..u64::MAX);
    format!("{a:016x}-{b:016x}-{c:016x}-{d:016x}")
}

#[cfg(test)]
mod tests {
    use super::{generate_boundary, MultipartForm, Part};
    use axum::{body::Body, http};
    use axum::{routing::get, Router};
    use http::{Request, Response};
    use http_body_util::BodyExt;
    use mime::Mime;
    use tower::ServiceExt;

    #[tokio::test]
    async fn process_form() -> Result<(), Box<dyn std::error::Error>> {
        // create a boilerplate handle that returns a form
        async fn handle() -> MultipartForm {
            let parts: Vec<Part> = vec![
                Part::text("part1".to_owned(), "basictext"),
                Part::file(

Review comment (suggestion):
```suggestion
/// A boundary is defined as a user defined (arbitrary) value that does not occur in any of the data.
///
```

Code after:
        let mut serialized_part = format!("Content-Disposition: form-data; name=\"{}\"", self.name);
        // specify a filename if one was set
        if let Some(filename) = &self.filename {
            serialized_part += &format!("; filename=\"{}\"", filename);
        }
        serialized_part += "\r\n";
        // specify the MIME type
        serialized_part += &format!("Content-Type: {}\r\n", self.mime_type);
        serialized_part += "\r\n";
        let mut part_bytes = serialized_part.as_bytes().to_vec();
        part_bytes.extend_from_slice(&self.contents);
        part_bytes.extend_from_slice(b"\r\n");

        part_bytes
    }
}

impl FromIterator<Part> for MultipartForm {
    fn from_iter<T: IntoIterator<Item = Part>>(iter: T) -> Self {
        Self {
            parts: iter.into_iter().collect(),
        }
    }
}

/// A boundary is defined as a user defined (arbitrary) value that does not occur in any of the data.
///
/// Because the specification does not clearly define a methodology for generating boundaries, this implementation
/// follow's Reqwest's, and generates a boundary in the format of `XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX` where `XXXXXXXX`
/// is a hexadecimal representation of a pseudo randomly generated u64.
fn generate_boundary() -> String {
    let a = fastrand::u64(0..u64::MAX);
    let b = fastrand::u64(0..u64::MAX);
    let c = fastrand::u64(0..u64::MAX);
    let d = fastrand::u64(0..u64::MAX);
    format!("{a:016x}-{b:016x}-{c:016x}-{d:016x}")
}

#[cfg(test)]
mod tests {
    use super::{generate_boundary, MultipartForm, Part};
    use axum::{body::Body, http};
    use axum::{routing::get, Router};
    use http::{Request, Response};
    use http_body_util::BodyExt;
    use mime::Mime;
    use tower::ServiceExt;

    #[tokio::test]
    async fn process_form() -> Result<(), Box<dyn std::error::Error>> {
        // create a boilerplate handle that returns a form