use once_cell::sync::Lazy;
use regex::Regex;
use super::CmdResult;
use crate::AnyRes as _;
use crate::Result;
pub static REGEX_R_LOG: Lazy<Regex> = Lazy::new(|| Regex::new(r"R<(?s:.*?)>R").unwrap());
#[inline]
pub fn parse_rlog_str(stdout: String) -> Result<String> {
if let Some(plog) = parse_rlog(&stdout) {
let plog = plog?;
if !plog.status {
return Err(plog.content.into());
}
Ok(plog.content)
} else {
Ok(stdout)
}
}
#[inline]
pub fn parse_rlog(stdout: &str) -> Option<Result<CmdResult<serde_json::Value>>> {
if let Some(cap) = REGEX_R_LOG.find_iter(stdout).last() {
let json_str = &stdout[cap.start() + 2..cap.end() - 2];
Some(serde_json::from_str::<CmdResult<serde_json::Value>>(json_str).any())
} else {
None
}
}
#[inline]
pub fn parse_and_validate_log(stdout: &str) -> Result<String> {
match parse_rlog(stdout) {
Some(Ok(res)) if res.status => Ok(res.content.to_string()),
Some(Ok(res)) => Err(res.content.into()),
Some(Err(e)) => Err(e.to_string().into()),
None => Err(format!("{}...", &crate::share::get_safe_preview(stdout, 200)).into()),
}
}
#[cfg(feature = "tokio")]
#[inline]
pub async fn a_parse_and_validate_log(stdout: &str) -> crate::Result<String> {
use crate::share::get_safe_preview;
use memchr::memmem::find;
let stdout_clone = stdout.to_owned();
let result = tokio::task::spawn_blocking(move || {
if let Some(start_pos) = find(stdout_clone.as_bytes(), b"R<") {
if let Some(cap) = REGEX_R_LOG.find_at(&stdout_clone, start_pos) {
let json_str = &stdout_clone[cap.start() + 2..cap.end() - 2];
match serde_json::from_str::<CmdResult<serde_json::Value>>(json_str) {
Ok(res) if res.status => Ok(res.content),
Ok(res) => Err(res.content),
Err(_) => Err(format!("{}...", &get_safe_preview(stdout_clone, 100))),
}
} else {
Err("Cannot find R<...>R tag".into())
}
} else {
Err("Cannot find start position R<".into())
}
})
.await
.map_err(|_| "Thread error: a_parse_and_validate_log")??;
Ok(result)
}