feat: 添加 GBK 解码支持,优化 BashTool 中的输出处理逻辑
This commit is contained in:
parent
23b7497b12
commit
b33350c410
@ -36,3 +36,4 @@ meval = "0.2"
|
|||||||
rusqlite = { version = "0.32", features = ["bundled"] }
|
rusqlite = { version = "0.32", features = ["bundled"] }
|
||||||
rustls = { version = "0.23", features = ["ring"] }
|
rustls = { version = "0.23", features = ["ring"] }
|
||||||
wechatbot = { path = "vendor/wechatbot" }
|
wechatbot = { path = "vendor/wechatbot" }
|
||||||
|
encoding_rs = "0.8"
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncReadExt, BufReader};
|
use tokio::io::{AsyncRead, AsyncReadExt, BufReader};
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
use tokio::sync::{Mutex, mpsc};
|
use tokio::sync::{Mutex, mpsc};
|
||||||
use tokio::time::{Instant, sleep_until};
|
use tokio::time::{Instant, sleep_until};
|
||||||
@ -392,25 +392,51 @@ where
|
|||||||
R: AsyncRead + Unpin + Send + 'static,
|
R: AsyncRead + Unpin + Send + 'static,
|
||||||
{
|
{
|
||||||
let mut reader = BufReader::new(stream);
|
let mut reader = BufReader::new(stream);
|
||||||
let mut line = String::new();
|
let mut buffer = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
line.clear();
|
let mut chunk = [0u8; 4096];
|
||||||
match reader.read_line(&mut line).await {
|
match reader.read(&mut chunk).await {
|
||||||
Ok(0) => break,
|
Ok(0) => break,
|
||||||
Ok(_) => {
|
Ok(n) => {
|
||||||
let _ = tx.send((is_stderr, line.clone()));
|
buffer.extend_from_slice(&chunk[..n]);
|
||||||
|
|
||||||
|
// 处理完整的行
|
||||||
|
while let Some(pos) = buffer.iter().position(|&b| b == b'\n') {
|
||||||
|
let line_bytes = &buffer[..pos + 1];
|
||||||
|
let line = decode_bytes(line_bytes);
|
||||||
|
let _ = tx.send((is_stderr, line));
|
||||||
|
buffer.drain(..pos + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut remainder = String::new();
|
// 处理剩余的字节
|
||||||
if reader.read_to_string(&mut remainder).await.is_ok() && !remainder.is_empty() {
|
if !buffer.is_empty() {
|
||||||
|
let remainder = decode_bytes(&buffer);
|
||||||
let _ = tx.send((is_stderr, remainder));
|
let _ = tx.send((is_stderr, remainder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 尝试 UTF-8 解码,失败则尝试 GBK 解码
|
||||||
|
fn decode_bytes(bytes: &[u8]) -> String {
|
||||||
|
// 首先尝试 UTF-8
|
||||||
|
if let Ok(s) = std::str::from_utf8(bytes) {
|
||||||
|
return s.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试 GBK 解码
|
||||||
|
let (cow, _, had_errors) = encoding_rs::GBK.decode(bytes);
|
||||||
|
if !had_errors {
|
||||||
|
return cow.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果 GBK 也失败,使用 lossy 转换
|
||||||
|
String::from_utf8_lossy(bytes).to_string()
|
||||||
|
}
|
||||||
|
|
||||||
fn format_command_output(stdout: &str, stderr: &str, exit_code: Option<i32>) -> String {
|
fn format_command_output(stdout: &str, stderr: &str, exit_code: Option<i32>) -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user