chore: rustfmt, clippy lints and code tidying
This commit is contained in:
1 parent
3716c3e698
commit
1752753fcc
19 files changed
+1273
-738
No files matched your search
+169
-108
@@ -20,19 +20,25 @@ pub struct JsonRpcResponse {
|
||||
pub error: Option<Value>,
|
||||
}
|
||||
|
||||
pub async fn read_message<R: tokio::io::AsyncRead + Unpin>(stdin: &mut BufReader<R>) -> Option<JsonRpcRequest> {
|
||||
pub async fn read_message<R: tokio::io::AsyncRead + Unpin>(
|
||||
stdin: &mut BufReader<R>,
|
||||
) -> Option<JsonRpcRequest> {
|
||||
let mut length = 0;
|
||||
loop {
|
||||
let mut line = String::new();
|
||||
if stdin.read_line(&mut line).await.unwrap_or(0) == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
if line.starts_with('{') {
|
||||
return match serde_json::from_str::<JsonRpcRequest>(line.trim_end()) {
|
||||
Ok(req) => Some(req),
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to parse JSON-RPC request from JSONL: {}. Payload: {}", e, line);
|
||||
tracing::error!(
|
||||
"Failed to parse JSON-RPC request from JSONL: {}. Payload: {}",
|
||||
e,
|
||||
line
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
@@ -52,13 +58,21 @@ pub async fn read_message<R: tokio::io::AsyncRead + Unpin>(stdin: &mut BufReader
|
||||
}
|
||||
let mut buffer = vec![0; length];
|
||||
stdin.read_exact(&mut buffer).await.unwrap_or(0);
|
||||
|
||||
|
||||
serde_json::from_slice(&buffer).ok()
|
||||
}
|
||||
|
||||
pub async fn send_response(response: JsonRpcResponse) {
|
||||
let msg = serde_json::to_string(&response).unwrap();
|
||||
tracing::info!("Sending JSON-RPC response (id: {:?}): {}", response.id, if msg.len() > 500 { format!("{}...", &msg[..500]) } else { msg.clone() });
|
||||
tracing::info!(
|
||||
"Sending JSON-RPC response (id: {:?}): {}",
|
||||
response.id,
|
||||
if msg.len() > 500 {
|
||||
format!("{}...", &msg[..500])
|
||||
} else {
|
||||
msg.clone()
|
||||
}
|
||||
);
|
||||
// CRITICAL ARCHITECTURAL DECISION:
|
||||
// The MCP StdioTransport MUST use Newline-Delimited JSON (NDJSON).
|
||||
// Do NOT use LSP-style HTTP headers (e.g. Content-Length).
|
||||
@@ -75,14 +89,16 @@ pub async fn send_error(id: Value, code: i32, message: &str) {
|
||||
id,
|
||||
result: None,
|
||||
error: Some(serde_json::json!({"code": code, "message": message})),
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
async fn get_socket_path() -> Result<String, String> {
|
||||
let profile = std::env::var("USERPROFILE").unwrap_or_else(|_| "C:\\Users\\reazul.ashraf".into());
|
||||
let profile =
|
||||
std::env::var("USERPROFILE").unwrap_or_else(|_| "C:\\Users\\reazul.ashraf".into());
|
||||
let path = format!("{}\\.gemini\\active_nvim.txt", profile);
|
||||
|
||||
|
||||
if let Ok(content) = std::fs::read_to_string(&path) {
|
||||
let p = content.trim().to_string();
|
||||
if !p.is_empty() {
|
||||
@@ -120,7 +136,7 @@ async fn get_socket_path() -> Result<String, String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if let Ok(entries) = std::fs::read_dir("/tmp") {
|
||||
for entry in entries.flatten() {
|
||||
if let Ok(name) = entry.file_name().into_string() {
|
||||
@@ -138,20 +154,28 @@ async fn get_socket_path() -> Result<String, String> {
|
||||
#[cfg(windows)]
|
||||
async fn call_nvim(req: rmpv::Value) -> Result<rmpv::Value, String> {
|
||||
use tokio::net::windows::named_pipe::ClientOptions;
|
||||
|
||||
|
||||
let msgid = if let rmpv::Value::Array(ref arr) = req {
|
||||
if arr.len() > 1 { arr[1].clone() } else { rmpv::Value::Nil }
|
||||
} else { rmpv::Value::Nil };
|
||||
if arr.len() > 1 {
|
||||
arr[1].clone()
|
||||
} else {
|
||||
rmpv::Value::Nil
|
||||
}
|
||||
} else {
|
||||
rmpv::Value::Nil
|
||||
};
|
||||
|
||||
tracing::info!("Connecting to neovim pipe");
|
||||
let socket_path = get_socket_path().await?;
|
||||
let mut client = ClientOptions::new().open(&socket_path).map_err(|e| e.to_string())?;
|
||||
|
||||
let mut client = ClientOptions::new()
|
||||
.open(&socket_path)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
rmpv::encode::write_value(&mut buf, &req).map_err(|e| e.to_string())?;
|
||||
tracing::info!("Sending RPC request to neovim (msgid: {})", msgid);
|
||||
client.write_all(&buf).await.map_err(|e| e.to_string())?;
|
||||
|
||||
|
||||
let mut resp_buf = Vec::new();
|
||||
let mut chunk = vec![0u8; 8192];
|
||||
let mut offset = 0;
|
||||
@@ -161,20 +185,23 @@ async fn call_nvim(req: rmpv::Value) -> Result<rmpv::Value, String> {
|
||||
match rmpv::decode::read_value(&mut cursor) {
|
||||
Ok(val) => {
|
||||
offset += cursor.position() as usize;
|
||||
|
||||
|
||||
if let rmpv::Value::Array(ref arr) = val {
|
||||
if arr.len() >= 4 && arr[0] == rmpv::Value::Integer(1.into()) && arr[1] == msgid {
|
||||
if arr.len() >= 4 && arr[0] == rmpv::Value::Integer(1.into()) && arr[1] == msgid
|
||||
{
|
||||
tracing::info!("Received RPC response from neovim (msgid: {})", msgid);
|
||||
return Ok(val);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
},
|
||||
}
|
||||
Err(_) => {
|
||||
let read_future = client.read(&mut chunk);
|
||||
match tokio::time::timeout(tokio::time::Duration::from_secs(5), read_future).await {
|
||||
Ok(Ok(n)) => {
|
||||
if n == 0 { return Err("Connection closed".into()); }
|
||||
if n == 0 {
|
||||
return Err("Connection closed".into());
|
||||
}
|
||||
resp_buf.extend_from_slice(&chunk[..n]);
|
||||
}
|
||||
Ok(Err(e)) => return Err(e.to_string()),
|
||||
@@ -193,18 +220,26 @@ async fn call_nvim(req: rmpv::Value) -> Result<rmpv::Value, String> {
|
||||
use tokio::net::UnixStream;
|
||||
|
||||
let msgid = if let rmpv::Value::Array(ref arr) = req {
|
||||
if arr.len() > 1 { arr[1].clone() } else { rmpv::Value::Nil }
|
||||
} else { rmpv::Value::Nil };
|
||||
if arr.len() > 1 {
|
||||
arr[1].clone()
|
||||
} else {
|
||||
rmpv::Value::Nil
|
||||
}
|
||||
} else {
|
||||
rmpv::Value::Nil
|
||||
};
|
||||
|
||||
tracing::info!("Connecting to neovim socket");
|
||||
let socket_path = get_socket_path().await?;
|
||||
let mut stream = UnixStream::connect(socket_path).await.map_err(|e| e.to_string())?;
|
||||
|
||||
let mut stream = UnixStream::connect(socket_path)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
rmpv::encode::write_value(&mut buf, &req).map_err(|e| e.to_string())?;
|
||||
tracing::info!("Sending RPC request to neovim (msgid: {})", msgid);
|
||||
stream.write_all(&buf).await.map_err(|e| e.to_string())?;
|
||||
|
||||
|
||||
let mut resp_buf = Vec::new();
|
||||
let mut chunk = vec![0u8; 8192];
|
||||
let mut offset = 0;
|
||||
@@ -214,20 +249,23 @@ async fn call_nvim(req: rmpv::Value) -> Result<rmpv::Value, String> {
|
||||
match rmpv::decode::read_value(&mut cursor) {
|
||||
Ok(val) => {
|
||||
offset += cursor.position() as usize;
|
||||
|
||||
|
||||
if let rmpv::Value::Array(ref arr) = val {
|
||||
if arr.len() >= 4 && arr[0] == rmpv::Value::Integer(1.into()) && arr[1] == msgid {
|
||||
if arr.len() >= 4 && arr[0] == rmpv::Value::Integer(1.into()) && arr[1] == msgid
|
||||
{
|
||||
tracing::info!("Received RPC response from neovim (msgid: {})", msgid);
|
||||
return Ok(val);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
},
|
||||
}
|
||||
Err(_) => {
|
||||
let read_future = stream.read(&mut chunk);
|
||||
match tokio::time::timeout(tokio::time::Duration::from_secs(5), read_future).await {
|
||||
Ok(Ok(n)) => {
|
||||
if n == 0 { return Err("Connection closed".into()); }
|
||||
if n == 0 {
|
||||
return Err("Connection closed".into());
|
||||
}
|
||||
resp_buf.extend_from_slice(&chunk[..n]);
|
||||
}
|
||||
Ok(Err(e)) => return Err(e.to_string()),
|
||||
@@ -248,7 +286,7 @@ async fn send_nvim_command(cmd: &str) -> Result<(), String> {
|
||||
RmpValue::String("nvim_command".into()),
|
||||
RmpValue::Array(vec![RmpValue::String(cmd.into())]),
|
||||
]);
|
||||
|
||||
|
||||
let resp = call_nvim(req).await?;
|
||||
if let RmpValue::Array(arr) = resp {
|
||||
if !arr[2].is_nil() {
|
||||
@@ -272,7 +310,7 @@ async fn get_nvim_active_buffer() -> Result<String, String> {
|
||||
RmpValue::Boolean(true),
|
||||
]),
|
||||
]);
|
||||
|
||||
|
||||
let resp = call_nvim(req).await?;
|
||||
if let RmpValue::Array(arr) = resp {
|
||||
if !arr[2].is_nil() {
|
||||
@@ -300,11 +338,9 @@ async fn get_nvim_cursor() -> Result<String, String> {
|
||||
RmpValue::Integer(0.into()),
|
||||
RmpValue::Integer(3.into()), // msgid
|
||||
RmpValue::String("nvim_win_get_cursor".into()),
|
||||
RmpValue::Array(vec![
|
||||
RmpValue::Integer(0.into()),
|
||||
]),
|
||||
RmpValue::Array(vec![RmpValue::Integer(0.into())]),
|
||||
]);
|
||||
|
||||
|
||||
let resp = call_nvim(req).await?;
|
||||
if let RmpValue::Array(arr) = resp {
|
||||
if !arr[2].is_nil() {
|
||||
@@ -332,7 +368,7 @@ async fn get_nvim_visual_selection() -> Result<String, String> {
|
||||
return lines
|
||||
end
|
||||
"#;
|
||||
|
||||
|
||||
use rmpv::Value as RmpValue;
|
||||
let req = RmpValue::Array(vec![
|
||||
RmpValue::Integer(0.into()),
|
||||
@@ -343,7 +379,7 @@ async fn get_nvim_visual_selection() -> Result<String, String> {
|
||||
RmpValue::Array(vec![]),
|
||||
]),
|
||||
]);
|
||||
|
||||
|
||||
let resp = call_nvim(req).await?;
|
||||
if let RmpValue::Array(arr) = resp {
|
||||
if !arr[2].is_nil() {
|
||||
@@ -360,7 +396,8 @@ async fn get_nvim_visual_selection() -> Result<String, String> {
|
||||
|
||||
async fn set_nvim_diagnostics(line: i64, message: &str) -> Result<(), String> {
|
||||
let escaped_message = message.replace("\\", "\\\\").replace("\"", "\\\"");
|
||||
let lua_script = format!(r#"
|
||||
let lua_script = format!(
|
||||
r#"
|
||||
local ns = vim.api.nvim_create_namespace("gemini_diagnostics")
|
||||
local diagnostics = {{{{
|
||||
lnum = {} - 1,
|
||||
@@ -369,8 +406,10 @@ async fn set_nvim_diagnostics(line: i64, message: &str) -> Result<(), String> {
|
||||
message = "{}",
|
||||
}}}}
|
||||
vim.diagnostic.set(ns, 0, diagnostics, {{}})
|
||||
"#, line, escaped_message);
|
||||
|
||||
"#,
|
||||
line, escaped_message
|
||||
);
|
||||
|
||||
use rmpv::Value as RmpValue;
|
||||
let req = RmpValue::Array(vec![
|
||||
RmpValue::Integer(0.into()),
|
||||
@@ -381,7 +420,7 @@ async fn set_nvim_diagnostics(line: i64, message: &str) -> Result<(), String> {
|
||||
RmpValue::Array(vec![]),
|
||||
]),
|
||||
]);
|
||||
|
||||
|
||||
let resp = call_nvim(req).await?;
|
||||
if let RmpValue::Array(arr) = resp {
|
||||
if !arr[2].is_nil() {
|
||||
@@ -404,7 +443,7 @@ fn rmpv_to_json(val: &rmpv::Value) -> serde_json::Value {
|
||||
} else {
|
||||
serde_json::Value::Null
|
||||
}
|
||||
},
|
||||
}
|
||||
rmpv::Value::F32(f) => serde_json::json!(f),
|
||||
rmpv::Value::F64(f) => serde_json::json!(f),
|
||||
rmpv::Value::String(s) => {
|
||||
@@ -413,11 +452,11 @@ fn rmpv_to_json(val: &rmpv::Value) -> serde_json::Value {
|
||||
} else {
|
||||
serde_json::Value::Null
|
||||
}
|
||||
},
|
||||
}
|
||||
rmpv::Value::Array(arr) => {
|
||||
let vec: Vec<serde_json::Value> = arr.iter().map(rmpv_to_json).collect();
|
||||
serde_json::Value::Array(vec)
|
||||
},
|
||||
}
|
||||
rmpv::Value::Map(map) => {
|
||||
let mut obj = serde_json::Map::new();
|
||||
for (k, v) in map {
|
||||
@@ -429,7 +468,7 @@ fn rmpv_to_json(val: &rmpv::Value) -> serde_json::Value {
|
||||
obj.insert(key_str, rmpv_to_json(v));
|
||||
}
|
||||
serde_json::Value::Object(obj)
|
||||
},
|
||||
}
|
||||
_ => serde_json::json!(format!("{:?}", val)),
|
||||
}
|
||||
}
|
||||
@@ -440,12 +479,9 @@ async fn execute_nvim_lua(code: &str) -> Result<String, String> {
|
||||
RmpValue::Integer(0.into()),
|
||||
RmpValue::Integer(6.into()), // msgid
|
||||
RmpValue::String("nvim_exec_lua".into()),
|
||||
RmpValue::Array(vec![
|
||||
RmpValue::String(code.into()),
|
||||
RmpValue::Array(vec![]),
|
||||
]),
|
||||
RmpValue::Array(vec![RmpValue::String(code.into()), RmpValue::Array(vec![])]),
|
||||
]);
|
||||
|
||||
|
||||
let resp = call_nvim(req).await?;
|
||||
if let RmpValue::Array(arr) = resp {
|
||||
if !arr[2].is_nil() {
|
||||
@@ -460,7 +496,12 @@ async fn execute_nvim_lua(code: &str) -> Result<String, String> {
|
||||
}
|
||||
pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
if std::env::args().any(|arg| arg == "--version") {
|
||||
println!("{} {} ({})", app_name, app_version, std::env::var("GIT_HASH").unwrap_or_else(|_| "unknown".to_string()));
|
||||
println!(
|
||||
"{} {} ({})",
|
||||
app_name,
|
||||
app_version,
|
||||
std::env::var("GIT_HASH").unwrap_or_else(|_| "unknown".to_string())
|
||||
);
|
||||
return;
|
||||
}
|
||||
let _guard = init_logging(app_name);
|
||||
@@ -471,7 +512,7 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
Some(m) => {
|
||||
tracing::info!("Received message method: {}", m.method);
|
||||
m
|
||||
},
|
||||
}
|
||||
None => {
|
||||
tracing::info!("Stdin closed, exiting loop");
|
||||
break;
|
||||
@@ -488,9 +529,14 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
match msg.method.as_str() {
|
||||
"initialize" => {
|
||||
let init = rmcp::model::InitializeResult::new(
|
||||
rmcp::model::ServerCapabilities::builder().enable_tools().build()
|
||||
rmcp::model::ServerCapabilities::builder()
|
||||
.enable_tools()
|
||||
.build(),
|
||||
)
|
||||
.with_server_info(rmcp::model::Implementation::new(app_name.clone(), app_version.clone()))
|
||||
.with_server_info(rmcp::model::Implementation::new(
|
||||
app_name.clone(),
|
||||
app_version.clone(),
|
||||
))
|
||||
.with_protocol_version(rmcp::model::ProtocolVersion::V_2024_11_05);
|
||||
|
||||
send_response(JsonRpcResponse {
|
||||
@@ -498,7 +544,8 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
id,
|
||||
result: Some(serde_json::to_value(init).unwrap()),
|
||||
error: None,
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
}
|
||||
"notifications/initialized" => {}
|
||||
"tools/list" => {
|
||||
@@ -595,7 +642,10 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
|
||||
match name {
|
||||
"nvim_goto_line" => {
|
||||
if let (Some(file), Some(line)) = (args.get("file").and_then(|v| v.as_str()), args.get("line").and_then(|v| v.as_i64())) {
|
||||
if let (Some(file), Some(line)) = (
|
||||
args.get("file").and_then(|v| v.as_str()),
|
||||
args.get("line").and_then(|v| v.as_i64()),
|
||||
) {
|
||||
let escaped_file = file.replace("\\", "\\\\");
|
||||
let cmd = format!("e {} | {} | normal! zz", escaped_file, line);
|
||||
match send_nvim_command(&cmd).await {
|
||||
@@ -615,53 +665,53 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
send_error(id, -32602, "Missing 'file' or 'line'").await;
|
||||
}
|
||||
}
|
||||
"nvim_get_active_buffer" => {
|
||||
match get_nvim_active_buffer().await {
|
||||
Ok(content) => {
|
||||
send_response(JsonRpcResponse {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
id,
|
||||
result: Some(json!({
|
||||
"content": [{"type": "text", "text": content}]
|
||||
})),
|
||||
error: None,
|
||||
}).await;
|
||||
}
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
"nvim_get_active_buffer" => match get_nvim_active_buffer().await {
|
||||
Ok(content) => {
|
||||
send_response(JsonRpcResponse {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
id,
|
||||
result: Some(json!({
|
||||
"content": [{"type": "text", "text": content}]
|
||||
})),
|
||||
error: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
"nvim_get_cursor" => {
|
||||
match get_nvim_cursor().await {
|
||||
Ok(content) => {
|
||||
send_response(JsonRpcResponse {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
id,
|
||||
result: Some(json!({
|
||||
"content": [{"type": "text", "text": content}]
|
||||
})),
|
||||
error: None,
|
||||
}).await;
|
||||
}
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
},
|
||||
"nvim_get_cursor" => match get_nvim_cursor().await {
|
||||
Ok(content) => {
|
||||
send_response(JsonRpcResponse {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
id,
|
||||
result: Some(json!({
|
||||
"content": [{"type": "text", "text": content}]
|
||||
})),
|
||||
error: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
"nvim_get_visual_selection" => {
|
||||
match get_nvim_visual_selection().await {
|
||||
Ok(content) => {
|
||||
send_response(JsonRpcResponse {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
id,
|
||||
result: Some(json!({
|
||||
"content": [{"type": "text", "text": content}]
|
||||
})),
|
||||
error: None,
|
||||
}).await;
|
||||
}
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
},
|
||||
"nvim_get_visual_selection" => match get_nvim_visual_selection().await {
|
||||
Ok(content) => {
|
||||
send_response(JsonRpcResponse {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
id,
|
||||
result: Some(json!({
|
||||
"content": [{"type": "text", "text": content}]
|
||||
})),
|
||||
error: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
},
|
||||
"nvim_set_diagnostics" => {
|
||||
if let (Some(line), Some(message)) = (args.get("line").and_then(|v| v.as_i64()), args.get("message").and_then(|v| v.as_str())) {
|
||||
if let (Some(line), Some(message)) = (
|
||||
args.get("line").and_then(|v| v.as_i64()),
|
||||
args.get("message").and_then(|v| v.as_str()),
|
||||
) {
|
||||
match set_nvim_diagnostics(line, message).await {
|
||||
Ok(_) => {
|
||||
send_response(JsonRpcResponse {
|
||||
@@ -700,7 +750,8 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
"content": [{"type": "text", "text": result}]
|
||||
})),
|
||||
error: None,
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
}
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
}
|
||||
@@ -730,7 +781,8 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
"content": [{"type": "text", "text": result}]
|
||||
})),
|
||||
error: None,
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
}
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
}
|
||||
@@ -746,7 +798,8 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
"content": [{"type": "text", "text": result}]
|
||||
})),
|
||||
error: None,
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
}
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
}
|
||||
@@ -770,18 +823,20 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
}
|
||||
|
||||
fn init_logging(app_name: &str) -> tracing_appender::non_blocking::WorkerGuard {
|
||||
let log_dir = dirs::home_dir().unwrap_or_default().join(".gemini/mcp_memory/logs");
|
||||
let log_dir = dirs::home_dir()
|
||||
.unwrap_or_default()
|
||||
.join(".gemini/mcp_memory/logs");
|
||||
std::fs::create_dir_all(&log_dir).unwrap_or_default();
|
||||
|
||||
|
||||
let file_appender = tracing_appender::rolling::daily(log_dir, format!("{}.log", app_name));
|
||||
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
|
||||
|
||||
|
||||
let _ = tracing_subscriber::fmt()
|
||||
.with_writer(non_blocking)
|
||||
.with_ansi(false)
|
||||
.with_max_level(tracing::Level::INFO)
|
||||
.try_init();
|
||||
|
||||
|
||||
guard
|
||||
}
|
||||
|
||||
@@ -794,7 +849,10 @@ mod tests {
|
||||
assert_eq!(rmpv_to_json(&rmpv::Value::Nil), serde_json::Value::Null);
|
||||
assert_eq!(rmpv_to_json(&rmpv::Value::Boolean(true)), json!(true));
|
||||
assert_eq!(rmpv_to_json(&rmpv::Value::Integer(42.into())), json!(42));
|
||||
assert_eq!(rmpv_to_json(&rmpv::Value::String("hello".into())), json!("hello"));
|
||||
assert_eq!(
|
||||
rmpv_to_json(&rmpv::Value::String("hello".into())),
|
||||
json!("hello")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -809,9 +867,12 @@ mod tests {
|
||||
#[test]
|
||||
fn test_rmpv_to_json_map() {
|
||||
let mut map = vec![];
|
||||
map.push((rmpv::Value::String("key1".into()), rmpv::Value::Integer(100.into())));
|
||||
map.push((
|
||||
rmpv::Value::String("key1".into()),
|
||||
rmpv::Value::Integer(100.into()),
|
||||
));
|
||||
let rmp_map = rmpv::Value::Map(map);
|
||||
|
||||
|
||||
let json_map = rmpv_to_json(&rmp_map);
|
||||
assert_eq!(json_map, json!({ "key1": 100 }));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user