use atomic_http::*;
use http::StatusCode;
use reqwest::multipart;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::{broadcast, Notify};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MultipartTestData {
pub id: u64,
pub description: String,
pub payload: Vec<u8>,
pub tags: Vec<String>,
pub metadata: HashMap<String, String>,
}
impl MultipartTestData {
pub fn generate(size_kb: usize) -> Self {
let payload_size = size_kb * 1024;
let mut metadata = HashMap::new();
metadata.insert("test".to_string(), "value".to_string());
metadata.insert("size".to_string(), size_kb.to_string());
metadata.insert("created_at".to_string(), chrono::Utc::now().to_rfc3339());
Self {
id: rand::random(),
description: format!("Test multipart data with {} KB", size_kb),
payload: vec![0u8; payload_size],
tags: vec![
"test".to_string(),
"multipart".to_string(),
"performance".to_string(),
],
metadata,
}
}
}
#[derive(Debug, Clone)]
pub struct MultipartTestResult {
pub test_name: String,
pub server_type: String,
pub file_count: usize,
pub total_size_mb: f64,
pub upload_time: Duration,
pub processing_time: Duration,
pub throughput_mbps: f64,
pub success: bool,
pub error: Option<String>,
}
pub struct IntegratedMultipartTest {
port: u16,
server_ready: Arc<Notify>,
test_results: Vec<MultipartTestResult>,
}
impl IntegratedMultipartTest {
pub fn new(port: u16) -> Self {
Self {
port,
server_ready: Arc::new(Notify::new()),
test_results: Vec::new(),
}
}
pub async fn run_integrated_multipart_test(&mut self) -> Result<(), SendableError> {
println!("๐ ํตํฉ ๋ฉํฐํํธ ํ
์คํธ ์์");
println!("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
self.prepare_test_environment().await?;
let (shutdown_tx, shutdown_rx) = broadcast::channel(1);
let server_ready = self.server_ready.clone();
let server_port = self.port;
let server_handle = tokio::spawn(async move {
if let Err(e) = Self::run_multipart_server(server_port, server_ready, shutdown_rx).await
{
eprintln!("โ ๋ฉํฐํํธ ์๋ฒ ์ค๋ฅ: {}", e);
}
});
println!("โณ ๋ฉํฐํํธ ์๋ฒ ์์ ๋๊ธฐ ์ค...");
self.server_ready.notified().await;
println!("โ
๋ฉํฐํํธ ์๋ฒ ์ค๋น ์๋ฃ!");
self.run_all_multipart_tests().await;
self.print_multipart_test_results();
println!("\n๐งน ํ
์คํธ ์ ๋ฆฌ ์ค...");
let _ = shutdown_tx.send(());
match tokio::time::timeout(Duration::from_secs(5), server_handle).await {
Ok(_) => println!("โ
์๋ฒ ์ ์ ์ข
๋ฃ"),
Err(_) => println!("โ ๏ธ ์๋ฒ ์ข
๋ฃ ํ์์์"),
}
Ok(())
}
async fn prepare_test_environment(&self) -> Result<(), SendableError> {
println!("๐ง ๋ฉํฐํํธ ํ
์คํธ ํ๊ฒฝ ์ค๋น ์ค...");
tokio::fs::create_dir_all("uploads").await.ok();
println!("โ
๋ฉํฐํํธ ํ
์คํธ ํ๊ฒฝ ์ค๋น ์๋ฃ");
Ok(())
}
async fn run_multipart_server(
port: u16,
server_ready: Arc<Notify>,
shutdown_rx: broadcast::Receiver<()>,
) -> Result<(), SendableError> {
println!("๐ฅ๏ธ ๋ฉํฐํํธ ์๋ฒ ์์ ์ค... (ํฌํธ: {})", port);
#[cfg(feature = "arena")]
{
Self::run_arena_multipart_server(port, server_ready, shutdown_rx).await
}
#[cfg(not(feature = "arena"))]
{
Self::run_standard_multipart_server(port, server_ready, shutdown_rx).await
}
}
#[cfg(feature = "arena")]
async fn run_arena_multipart_server(
port: u16,
server_ready: Arc<Notify>,
mut shutdown_rx: broadcast::Receiver<()>,
) -> Result<(), SendableError> {
let mut server = Server::new(&format!("127.0.0.1:{}", port)).await?;
server_ready.notify_one();
println!("โ
Arena ๋ฉํฐํํธ ์๋ฒ ์คํ ์ค (ํฌํธ: {})", port);
loop {
tokio::select! {
_ = shutdown_rx.recv() => {
println!("๐ ๋ฉํฐํํธ ์๋ฒ ์ข
๋ฃ ์ ํธ ์์ ");
break;
}
accept_result = server.accept() => {
match accept_result {
Ok(accept) => {
tokio::spawn(async move {
if let Err(e) = Self::handle_arena_multipart_request(accept).await {
eprintln!("Arena ๋ฉํฐํํธ ์์ฒญ ์ฒ๋ฆฌ ์ค๋ฅ: {}", e);
}
});
}
Err(e) => {
eprintln!("์ฐ๊ฒฐ ์๋ฝ ์ค๋ฅ: {}", e);
break;
}
}
}
}
}
Ok(())
}
#[cfg(not(feature = "arena"))]
async fn run_standard_multipart_server(
port: u16,
server_ready: Arc<Notify>,
mut shutdown_rx: broadcast::Receiver<()>,
) -> Result<(), SendableError> {
let mut server = Server::new(&format!("127.0.0.1:{}", port)).await?;
server_ready.notify_one();
println!("โ
ํ์ค ๋ฉํฐํํธ ์๋ฒ ์คํ ์ค (ํฌํธ: {})", port);
loop {
tokio::select! {
_ = shutdown_rx.recv() => {
println!("๐ ๋ฉํฐํํธ ์๋ฒ ์ข
๋ฃ ์ ํธ ์์ ");
break;
}
accept_result = server.accept() => {
match accept_result {
Ok(accept) => {
tokio::spawn(async move {
if let Err(e) = Self::handle_standard_multipart_request(accept).await {
eprintln!("ํ์ค ๋ฉํฐํํธ ์์ฒญ ์ฒ๋ฆฌ ์ค๋ฅ: {}", e);
}
});
}
Err(e) => {
eprintln!("์ฐ๊ฒฐ ์๋ฝ ์ค๋ฅ: {}", e);
break;
}
}
}
}
}
Ok(())
}
#[cfg(feature = "arena")]
async fn handle_arena_multipart_request(accept: Accept) -> Result<(), SendableError> {
match accept.parse_request_arena_writer().await {
Ok((request, mut response)) => {
let start_time = Instant::now();
let path = request.uri().path();
match path {
"/" => {
let info = serde_json::json!({
"message": "๐๏ธ Arena ๋ฉํฐํํธ ์๋ฒ",
"version": "1.0.0",
"features": ["arena", "zero_copy_multipart"],
"endpoints": ["/upload", "/test/json"]
});
response.body_mut().set_arena_json(&info)?;
*response.status_mut() = StatusCode::OK;
}
"/upload" => {
match request.get_multi_part_arena() {
Ok(Some(form)) => {
let process_time = start_time.elapsed();
let mut text_fields = HashMap::new();
for i in 0..form.text_fields.len() {
if let (Some(name), Some(value)) =
(form.get_text_field_name(i), form.get_text_field_value(i))
{
text_fields.insert(name.to_string(), value.to_string());
}
}
let files_info: Vec<serde_json::Value> = form.parts.iter().map(|part| {
serde_json::json!({
"name": part.get_name().unwrap_or("unknown"),
"filename": part.get_file_name().unwrap_or(""),
"size": part.get_body().len(),
"content_type": part.get_content_type().unwrap_or("application/octet-stream")
})
}).collect();
let total_size: usize =
form.parts.iter().map(|p| p.get_body().len()).sum();
let response_data = serde_json::json!({
"status": "success",
"server_type": "arena",
"text_fields": text_fields,
"file_count": form.parts.len(),
"files": files_info,
"total_size_bytes": total_size,
"processing_time_ms": process_time.as_millis(),
"memory_info": "zero_copy_arena_allocated",
"performance": {
"memory_copies": 0,
"string_allocations": 0,
"direct_byte_access": true
}
});
response.body_mut().set_arena_json(&response_data)?;
*response.status_mut() = StatusCode::OK;
for part in form.parts.iter() {
if let Some(filename) = part.get_file_name() {
if !filename.is_empty() {
let save_path = format!("uploads/arena_{}", filename);
if let Err(e) =
tokio::fs::write(&save_path, part.get_body()).await
{
eprintln!("ํ์ผ ์ ์ฅ ์คํจ {}: {}", save_path, e);
}
}
}
}
}
Ok(None) => {
match request.get_json_arena::<MultipartTestData>() {
Ok(data) => {
let process_time = start_time.elapsed();
let response_data = serde_json::json!({
"status": "success",
"server_type": "arena",
"data_type": "json",
"received_id": data.id,
"data_size": data.description.len() + data.payload.len(),
"processing_time_ms": process_time.as_millis(),
"memory_info": "zero_copy_json_parsing"
});
response.body_mut().set_arena_json(&response_data)?;
*response.status_mut() = StatusCode::OK;
}
Err(e) => {
eprintln!("JSON ํ์ฑ ์คํจ: {}", e);
*response.status_mut() = StatusCode::BAD_REQUEST;
response
.body_mut()
.set_arena_response("Invalid JSON data")?;
}
}
}
Err(e) => {
eprintln!("๋ฉํฐํํธ ํ์ฑ ์คํจ: {}", e);
*response.status_mut() = StatusCode::BAD_REQUEST;
response
.body_mut()
.set_arena_response("Multipart parsing failed")?;
}
}
}
_ => {
*response.status_mut() = StatusCode::NOT_FOUND;
response.body_mut().set_arena_response("Not found")?;
}
}
response.responser_arena().await?;
}
Err(e) => {
eprintln!("Arena ์์ฒญ ํ์ฑ ์คํจ: {}", e);
}
}
Ok(())
}
#[cfg(not(feature = "arena"))]
async fn handle_standard_multipart_request(accept: Accept) -> Result<(), SendableError> {
match accept.parse_request().await {
Ok((mut request, mut response)) => {
let start_time = Instant::now();
let path = request.uri().path();
match path {
"/" => {
let info = serde_json::json!({
"message": "๐ ํ์ค ๋ฉํฐํํธ ์๋ฒ",
"version": "1.0.0",
"features": ["standard"],
"endpoints": ["/upload", "/test/json"]
});
response.body_mut().body = info.to_string();
*response.status_mut() = StatusCode::OK;
}
"/upload" => {
match request.get_multi_part().await {
Ok(Some(form)) => {
let process_time = start_time.elapsed();
let total_size: usize =
form.parts.iter().map(|p| p.body.len()).sum();
let response_data = serde_json::json!({
"status": "success",
"server_type": "standard",
"text_fields": {
form.text.0: form.text.1
},
"file_count": form.parts.len(),
"files": form.parts.iter().map(|part| {
serde_json::json!({
"name": part.name,
"filename": part.file_name,
"size": part.body.len(),
"content_type": part.headers.get("content-type")
.map(|v| v.to_str().unwrap_or("unknown"))
.unwrap_or("unknown")
})
}).collect::<Vec<_>>(),
"total_size_bytes": total_size,
"processing_time_ms": process_time.as_millis(),
"memory_info": "heap_allocated_with_copies",
"performance": {
"memory_copies": "multiple",
"string_allocations": "many",
"direct_byte_access": false
}
});
response.body_mut().body = response_data.to_string();
*response.status_mut() = StatusCode::OK;
for part in &form.parts {
if !part.file_name.is_empty() {
let save_path =
format!("uploads/standard_{}", part.file_name);
if let Err(e) =
tokio::fs::write(&save_path, &part.body).await
{
eprintln!("ํ์ผ ์ ์ฅ ์คํจ {}: {}", save_path, e);
}
}
}
}
Ok(None) => match request.get_json::<MultipartTestData>() {
Ok(data) => {
let process_time = start_time.elapsed();
let response_data = serde_json::json!({
"status": "success",
"server_type": "standard",
"data_type": "json",
"received_id": data.id,
"data_size": data.description.len() + data.payload.len(),
"processing_time_ms": process_time.as_millis(),
"memory_info": "heap_allocated_json"
});
response.body_mut().body = response_data.to_string();
*response.status_mut() = StatusCode::OK;
}
Err(e) => {
eprintln!("JSON ํ์ฑ ์คํจ: {}", e);
*response.status_mut() = StatusCode::BAD_REQUEST;
}
},
Err(e) => {
eprintln!("๋ฉํฐํํธ ํ์ฑ ์คํจ: {}", e);
*response.status_mut() = StatusCode::BAD_REQUEST;
}
}
}
_ => {
*response.status_mut() = StatusCode::NOT_FOUND;
response.body_mut().body = "Not found".to_string();
}
}
response.responser().await?;
}
Err(e) => {
eprintln!("ํ์ค ์์ฒญ ํ์ฑ ์คํจ: {}", e);
}
}
Ok(())
}
async fn run_all_multipart_tests(&mut self) {
println!("\n๐งช ๋ฉํฐํํธ ํ
์คํธ ์คํ ์์");
println!("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
self.test_json_upload().await;
self.test_small_file_upload().await;
self.test_medium_file_upload().await;
self.test_large_file_upload().await;
self.test_multiple_file_upload().await;
self.test_extreme_upload().await;
}
async fn test_json_upload(&mut self) {
println!("\n๐ JSON ์
๋ก๋ ํ
์คํธ");
let sizes = vec![1, 10, 100]; for size_kb in sizes {
match self.execute_json_upload_test(size_kb).await {
Ok(result) => {
println!(
" โ
{}KB JSON: {:.1}ms",
size_kb,
result.processing_time.as_millis()
);
self.test_results.push(result);
}
Err(e) => {
println!(" โ {}KB JSON ์คํจ: {}", size_kb, e);
self.test_results.push(MultipartTestResult {
test_name: format!("JSON {}KB", size_kb),
server_type: "unknown".to_string(),
file_count: 0,
total_size_mb: 0.0,
upload_time: Duration::from_millis(0),
processing_time: Duration::from_millis(0),
throughput_mbps: 0.0,
success: false,
error: Some(e.to_string()),
});
}
}
}
}
async fn execute_json_upload_test(
&self,
size_kb: usize,
) -> Result<MultipartTestResult, SendableError> {
let client = reqwest::Client::new();
let url = format!("http://127.0.0.1:{}/upload", self.port);
let test_data = MultipartTestData::generate(size_kb);
let start = Instant::now();
let response = client
.post(&url)
.header("Content-Type", "application/json")
.json(&test_data)
.send()
.await?;
let upload_time = start.elapsed();
let body: serde_json::Value = response.json().await?;
let processing_time = Duration::from_millis(
body.get("processing_time_ms")
.and_then(|v| v.as_u64())
.unwrap_or(0),
);
let server_type = body
.get("server_type")
.and_then(|v| v.as_str())
.unwrap_or("unknown")
.to_string();
let size_mb = (size_kb as f64) / 1024.0;
let throughput_mbps = (size_mb * 8.0) / upload_time.as_secs_f64();
Ok(MultipartTestResult {
test_name: format!("JSON {}KB", size_kb),
server_type,
file_count: 0,
total_size_mb: size_mb,
upload_time,
processing_time,
throughput_mbps,
success: true,
error: None,
})
}
async fn test_small_file_upload(&mut self) {
println!("\n๐ ์์ฉ๋ ํ์ผ ์
๋ก๋ ํ
์คํธ");
let file_sizes = vec![1024, 5120, 10240];
match self
.execute_multipart_upload_test("์์ฉ๋ ํ์ผ๋ค", file_sizes)
.await
{
Ok(result) => {
println!(" โ
์๋ฃ: {:.1}MB/s", result.throughput_mbps);
self.test_results.push(result);
}
Err(e) => {
println!(" โ ์คํจ: {}", e);
}
}
}
async fn test_medium_file_upload(&mut self) {
println!("\n๐ ์ค์ฉ๋ ํ์ผ ์
๋ก๋ ํ
์คํธ");
let file_sizes = vec![102400, 204800, 512000];
match self
.execute_multipart_upload_test("์ค์ฉ๋ ํ์ผ๋ค", file_sizes)
.await
{
Ok(result) => {
println!(" โ
์๋ฃ: {:.1}MB/s", result.throughput_mbps);
self.test_results.push(result);
}
Err(e) => {
println!(" โ ์คํจ: {}", e);
}
}
}
async fn test_large_file_upload(&mut self) {
println!("\n๐๏ธ ๋์ฉ๋ ํ์ผ ์
๋ก๋ ํ
์คํธ");
let file_sizes = vec![1048576, 2097152];
match self
.execute_multipart_upload_test("๋์ฉ๋ ํ์ผ๋ค", file_sizes)
.await
{
Ok(result) => {
println!(" โ
์๋ฃ: {:.1}MB/s", result.throughput_mbps);
self.test_results.push(result);
}
Err(e) => {
println!(" โ ์คํจ: {}", e);
}
}
}
async fn test_multiple_file_upload(&mut self) {
println!("\n๐ ๋ค์ค ํ์ผ ์
๋ก๋ ํ
์คํธ");
let file_sizes = vec![524288; 5];
match self
.execute_multipart_upload_test("๋ค์ค ํ์ผ", file_sizes)
.await
{
Ok(result) => {
println!(
" โ
์๋ฃ: {}๊ฐ ํ์ผ, {:.1}MB/s",
result.file_count, result.throughput_mbps
);
self.test_results.push(result);
}
Err(e) => {
println!(" โ ์คํจ: {}", e);
}
}
}
async fn test_extreme_upload(&mut self) {
println!("\n๐ ๊ทนํ ์
๋ก๋ ํ
์คํธ");
let file_sizes = vec![10485760];
match self
.execute_multipart_upload_test("๊ทนํ ๋์ฉ๋", file_sizes)
.await
{
Ok(result) => {
println!(
" โ
์๋ฃ: {:.1}MB ํ์ผ, {:.1}MB/s",
result.total_size_mb, result.throughput_mbps
);
self.test_results.push(result);
}
Err(e) => {
println!(" โ ์คํจ: {}", e);
}
}
}
async fn execute_multipart_upload_test(
&self,
test_name: &str,
file_sizes: Vec<usize>,
) -> Result<MultipartTestResult, SendableError> {
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(60))
.build()?;
let url = format!("http://127.0.0.1:{}/upload", self.port);
let mut form = multipart::Form::new();
form = form.text("description", format!("ํ
์คํธ: {}", test_name));
form = form.text("user_id", "test_user_12345");
form = form.text("timestamp", chrono::Utc::now().to_rfc3339());
let total_size: usize = file_sizes.iter().sum();
for (i, size) in file_sizes.iter().enumerate() {
let file_data = vec![(i % 256) as u8; *size];
let part = multipart::Part::bytes(file_data)
.file_name(format!(
"test_file_{}_{}.bin",
test_name.replace(" ", "_"),
i
))
.mime_str("application/octet-stream")?;
form = form.part(format!("file_{}", i), part);
}
let start = Instant::now();
let response = client.post(&url).multipart(form).send().await?;
let upload_time = start.elapsed();
let body: serde_json::Value = response.json().await?;
let processing_time = Duration::from_millis(
body.get("processing_time_ms")
.and_then(|v| v.as_u64())
.unwrap_or(0),
);
let server_type = body
.get("server_type")
.and_then(|v| v.as_str())
.unwrap_or("unknown")
.to_string();
let file_count = file_sizes.len();
let total_size_mb = (total_size as f64) / (1024.0 * 1024.0);
let throughput_mbps = (total_size_mb * 8.0) / upload_time.as_secs_f64();
Ok(MultipartTestResult {
test_name: test_name.to_string(),
server_type,
file_count,
total_size_mb,
upload_time,
processing_time,
throughput_mbps,
success: true,
error: None,
})
}
fn print_multipart_test_results(&self) {
println!("\n๐ ๋ฉํฐํํธ ํ
์คํธ ๊ฒฐ๊ณผ ์์ฝ");
println!("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
let successful = self.test_results.iter().filter(|r| r.success).count();
let total = self.test_results.len();
println!(
"์ ์ฒด ํ
์คํธ: {} / ์ฑ๊ณต: {} / ์คํจ: {}",
total,
successful,
total - successful
);
println!("\n๐ ์์ธ ๊ฒฐ๊ณผ:");
println!(
"{:<20} {:<10} {:<8} {:<12} {:<12} {:<12}",
"ํ
์คํธ", "์๋ฒ", "ํ์ผ์", "ํฌ๊ธฐ(MB)", "์
๋ก๋(ms)", "์ฒ๋ฆฌ๋(MB/s)"
);
println!("{:-<80}", "");
for result in &self.test_results {
let status = if result.success { "โ
" } else { "โ" };
if result.success {
println!(
"{} {:<18} {:<10} {:<8} {:<12.2} {:<12.0} {:<12.1}",
status,
result.test_name,
result.server_type,
result.file_count,
result.total_size_mb,
result.upload_time.as_millis(),
result.throughput_mbps
);
} else {
println!("{} {:<18} {:<10} - - - -", status, result.test_name, "์คํจ");
if let Some(error) = &result.error {
println!(" ์ค๋ฅ: {}", error);
}
}
}
println!("\n๐ฏ ์ฑ๋ฅ ์์ฝ:");
let successful_results: Vec<_> = self.test_results.iter().filter(|r| r.success).collect();
if !successful_results.is_empty() {
let avg_throughput: f64 = successful_results
.iter()
.map(|r| r.throughput_mbps)
.sum::<f64>()
/ successful_results.len() as f64;
let max_throughput = successful_results
.iter()
.map(|r| r.throughput_mbps)
.fold(0.0f64, |a, b| a.max(b));
println!("ํ๊ท ์ฒ๋ฆฌ๋: {:.1} MB/s", avg_throughput);
println!("์ต๊ณ ์ฒ๋ฆฌ๋: {:.1} MB/s", max_throughput);
if let Some(server_type) = successful_results.first().map(|r| &r.server_type) {
println!("์๋ฒ ํ์
: {}", server_type);
#[cfg(feature = "arena")]
if server_type == "arena" {
println!("\n๐ก Arena ์๋ฒ์ ๋ฉํฐํํธ ์ฅ์ :");
println!(" โ
์ ๋ก์นดํผ: ํ์ผ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ์ง ์๊ณ ์ง์ ์ ๊ทผ");
println!(" โ
๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ: Arena ํ ๋น์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ต์ ํ");
println!(" โ
๋น ๋ฅธ ํ์ฑ: String ์์ฑ ์์ด ๋ฐ์ดํธ ์ง์ ์ฒ๋ฆฌ");
println!(" โ
๋ฎ์ GC ์๋ฐ: ๋ฉ๋ชจ๋ฆฌ ํ ๋น/ํด์ ๋ถ๋ด ์ต์ํ");
}
}
}
if successful == total {
println!("\n๐ ๋ชจ๋ ๋ฉํฐํํธ ํ
์คํธ ํต๊ณผ!");
} else {
println!(
"\nโ ๏ธ ์ผ๋ถ ๋ฉํฐํํธ ํ
์คํธ ์คํจ ({}/{})",
total - successful,
total
);
}
}
}
#[tokio::main]
async fn main() -> Result<(), SendableError> {
println!("๐ ํตํฉ ๋ฉํฐํํธ ํ
์คํธ ๋๊ตฌ");
#[cfg(feature = "arena")]
println!("๋ชจ๋: Arena + Zero-copy ๋ฉํฐํํธ");
#[cfg(not(feature = "arena"))]
println!("๋ชจ๋: ํ์ค ๋ฉํฐํํธ");
let port = 9090;
let mut test_manager = IntegratedMultipartTest::new(port);
test_manager.run_integrated_multipart_test().await?;
println!("\nโจ ํตํฉ ๋ฉํฐํํธ ํ
์คํธ ์๋ฃ!");
println!("\n๐ก ์ถ๊ฐ ํ
์คํธ ์คํ:");
println!(" Arena: cargo run --example integrated_multipart_test --features arena");
println!(" ํ์ค: cargo run --example integrated_multipart_test");
println!(" ๋ฆด๋ฆฌ์ฆ: cargo run --release --example integrated_multipart_test --features arena");
Ok(())
}