(content: &str, save_dir: &Path)
| 22 | |
| 23 | impl Truncate { |
| 24 | pub async fn output(content: &str, save_dir: &Path) -> std::io::Result<TruncationResult> { |
| 25 | let original_bytes = content.len(); |
| 26 | let original_lines = content.lines().count(); |
| 27 | |
| 28 | let needs_truncation = original_bytes > MAX_BYTES || original_lines > MAX_LINES; |
| 29 | |
| 30 | if !needs_truncation { |
| 31 | return Ok(TruncationResult { |
| 32 | truncated: false, |
| 33 | original_lines, |
| 34 | original_bytes, |
| 35 | truncated_lines: original_lines, |
| 36 | truncated_bytes: original_bytes, |
| 37 | saved_to: None, |
| 38 | }); |
| 39 | } |
| 40 | |
| 41 | let lines: Vec<&str> = content.lines().collect(); |
| 42 | let mut truncated_lines = lines.clone(); |
| 43 | |
| 44 | if truncated_lines.len() > MAX_LINES { |
| 45 | truncated_lines = truncated_lines.split_off(truncated_lines.len() - MAX_LINES); |
| 46 | } |
| 47 | |
| 48 | let mut truncated_content = truncated_lines.join("\n"); |
| 49 | |
| 50 | if truncated_content.len() > MAX_BYTES { |
| 51 | let bytes_to_take = MAX_BYTES.saturating_sub(100); |
| 52 | let start = truncated_content.len().saturating_sub(bytes_to_take); |
| 53 | truncated_content = format!("... [truncated]\n{}", &truncated_content[start..]); |
| 54 | } |
| 55 | |
| 56 | let truncated_bytes = truncated_content.len(); |
| 57 | let truncated_line_count = truncated_content.lines().count(); |
| 58 | |
| 59 | let saved_to = Self::save_truncated(&truncated_content, save_dir).await?; |
| 60 | |
| 61 | Ok(TruncationResult { |
| 62 | truncated: true, |
| 63 | original_lines, |
| 64 | original_bytes, |
| 65 | truncated_lines: truncated_line_count, |
| 66 | truncated_bytes, |
| 67 | saved_to: Some(saved_to), |
| 68 | }) |
| 69 | } |
| 70 | |
| 71 | async fn save_truncated(content: &str, save_dir: &Path) -> std::io::Result<PathBuf> { |
| 72 | fs::create_dir_all(save_dir).await?; |
no test coverage detected