regex: lazy_static everything instead of function input

This commit is contained in:
hinto.janai 2023-04-19 10:01:11 -04:00
parent bf4d286fad
commit c8e5462d33
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
7 changed files with 133 additions and 102 deletions

View file

@ -91,10 +91,11 @@ pub const P2POOL_FAILED: &str = "P2Pool is offline and failed when exiting";
pub const P2POOL_MIDDLE: &str = "P2Pool is in the middle of (re)starting/stopping";
pub const P2POOL_SYNCING: &str = "P2Pool is still syncing. This indicator will turn GREEN when P2Pool is ready";
pub const XMRIG_ALIVE: &str = "XMRig is online";
pub const XMRIG_ALIVE: &str = "XMRig is online and mining";
pub const XMRIG_DEAD: &str = "XMRig is offline";
pub const XMRIG_FAILED: &str = "XMRig is offline and failed when exiting";
pub const XMRIG_MIDDLE: &str = "XMRig is in the middle of (re)starting/stopping";
pub const XMRIG_NOT_MINING: &str = "XMRig is online, but not mining to any pool";
// This is the typical space added when using
// [ui.separator()] or [ui.group()]

View file

@ -47,7 +47,6 @@ use crate::{
SudoState,
human::*,
GupaxP2poolApi,
P2poolRegex,
xmr::*,
macros::*,
RemoteNode,
@ -56,6 +55,10 @@ use sysinfo::SystemExt;
use serde::{Serialize,Deserialize};
use sysinfo::{CpuExt,ProcessExt};
use log::*;
use crate::regex::{
P2POOL_REGEX,
XMRIG_REGEX,
};
//---------------------------------------------------------------------------------------------------- Constants
// The max amount of bytes of process output we are willing to
@ -182,7 +185,8 @@ impl Process {
pub fn is_alive(&self) -> bool {
self.state == ProcessState::Alive ||
self.state == ProcessState::Middle ||
self.state == ProcessState::Syncing
self.state == ProcessState::Syncing ||
self.state == ProcessState::NotMining
}
pub fn is_waiting(&self) -> bool {
@ -192,6 +196,10 @@ impl Process {
pub fn is_syncing(&self) -> bool {
self.state == ProcessState::Syncing
}
pub fn is_not_mining(&self) -> bool {
self.state == ProcessState::NotMining
}
}
//---------------------------------------------------------------------------------------------------- [Process*] Enum
@ -205,6 +213,9 @@ pub enum ProcessState {
// Only for P2Pool, ORANGE.
Syncing,
// Only for XMRig, ORANGE.
NotMining,
}
impl Default for ProcessState { fn default() -> Self { Self::Dead } }
@ -267,14 +278,14 @@ impl Helper {
}
}
fn read_pty_p2pool(output_parse: Arc<Mutex<String>>, output_pub: Arc<Mutex<String>>, reader: Box<dyn std::io::Read + Send>, regex: P2poolRegex, gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>) {
fn read_pty_p2pool(output_parse: Arc<Mutex<String>>, output_pub: Arc<Mutex<String>>, reader: Box<dyn std::io::Read + Send>, gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>) {
use std::io::BufRead;
let mut stdout = std::io::BufReader::new(reader).lines();
while let Some(Ok(line)) = stdout.next() {
// println!("{}", line); // For debugging.
if regex.payout.is_match(&line) {
if P2POOL_REGEX.payout.is_match(&line) {
debug!("P2Pool PTY | Found payout, attempting write: {}", line);
let (date, atomic_unit, block) = PayoutOrd::parse_raw_payout_line(&line, &regex);
let (date, atomic_unit, block) = PayoutOrd::parse_raw_payout_line(&line);
let formatted_log_line = GupaxP2poolApi::format_payout(&date, &atomic_unit, &block);
GupaxP2poolApi::add_payout(&mut lock!(gupax_p2pool_api), &formatted_log_line, date, atomic_unit, block);
if let Err(e) = GupaxP2poolApi::write_to_all_files(&lock!(gupax_p2pool_api), &formatted_log_line) { error!("P2Pool PTY GupaxP2poolApi | Write error: {}", e); }
@ -496,16 +507,13 @@ impl Helper {
let mut stdin = pair.master;
drop(lock);
let regex = P2poolRegex::new();
// 3. Spawn PTY read thread
debug!("P2Pool | Spawning PTY read thread...");
let output_parse = Arc::clone(&lock!(process).output_parse);
let output_pub = Arc::clone(&lock!(process).output_pub);
let gupax_p2pool_api = Arc::clone(&gupax_p2pool_api);
let regex_clone = regex.clone();
thread::spawn(move || {
Self::read_pty_p2pool(output_parse, output_pub, reader, regex_clone, gupax_p2pool_api);
Self::read_pty_p2pool(output_parse, output_pub, reader, gupax_p2pool_api);
});
let output_parse = Arc::clone(&lock!(process).output_parse);
let output_pub = Arc::clone(&lock!(process).output_pub);
@ -657,7 +665,7 @@ impl Helper {
// Always update from output
debug!("P2Pool Watchdog | Starting [update_from_output()]");
PubP2poolApi::update_from_output(&pub_api, &output_parse, &output_pub, start.elapsed(), &regex, &process);
PubP2poolApi::update_from_output(&pub_api, &output_parse, &output_pub, start.elapsed(), &process);
// Read [local] API
debug!("P2Pool Watchdog | Attempting [local] API file read");
@ -1369,12 +1377,12 @@ impl PubP2poolApi {
// Essentially greps the output for [x.xxxxxxxxxxxx XMR] where x = a number.
// It sums each match and counts along the way, handling an error by not adding and printing to console.
fn calc_payouts_and_xmr(output: &str, regex: &P2poolRegex) -> (u128 /* payout count */, f64 /* total xmr */) {
let iter = regex.payout.find_iter(output);
fn calc_payouts_and_xmr(output: &str) -> (u128 /* payout count */, f64 /* total xmr */) {
let iter = P2POOL_REGEX.payout.find_iter(output);
let mut sum: f64 = 0.0;
let mut count: u128 = 0;
for i in iter {
if let Some(word) = regex.payout_float.find(i.as_str()) {
if let Some(word) = P2POOL_REGEX.payout_float.find(i.as_str()) {
match word.as_str().parse::<f64>() {
Ok(num) => { sum += num; count += 1; },
Err(e) => error!("P2Pool | Total XMR sum calculation error: [{}]", e),
@ -1390,7 +1398,6 @@ impl PubP2poolApi {
output_parse: &Arc<Mutex<String>>,
output_pub: &Arc<Mutex<String>>,
elapsed: std::time::Duration,
regex: &P2poolRegex,
process: &Arc<Mutex<Process>>,
) {
// 1. Take the process's current output buffer and combine it with Pub (if not empty)
@ -1401,10 +1408,10 @@ impl PubP2poolApi {
// 2. Parse the full STDOUT
let mut output_parse = lock!(output_parse);
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse, regex);
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse);
// Check for "SYNCHRONIZED" only if we aren't already.
if lock!(process).state == ProcessState::Syncing {
if regex.synchronized.is_match(&output_parse) {
if P2POOL_REGEX.synchronized.is_match(&output_parse) {
lock!(process).state = ProcessState::Alive;
}
}
@ -1917,37 +1924,32 @@ mod test {
#[test]
fn combine_gui_pub_p2pool_api() {
use crate::helper::PubP2poolApi;
let mut gui_api = PubP2poolApi::new();
let mut pub_api = PubP2poolApi::new();
pub_api.payouts = 1;
pub_api.payouts_hour = 2.0;
pub_api.payouts_day = 3.0;
pub_api.payouts_month = 4.0;
pub_api.xmr = 1.0;
pub_api.xmr_hour = 2.0;
pub_api.xmr_day = 3.0;
pub_api.xmr_month = 4.0;
println!("BEFORE - GUI_API: {:#?}\nPUB_API: {:#?}", gui_api, pub_api);
assert_ne!(gui_api, pub_api);
PubP2poolApi::combine_gui_pub_api(&mut gui_api, &mut pub_api);
println!("AFTER - GUI_API: {:#?}\nPUB_API: {:#?}", gui_api, pub_api);
assert_eq!(gui_api, pub_api);
pub_api.xmr = 2.0;
PubP2poolApi::combine_gui_pub_api(&mut gui_api, &mut pub_api);
assert_eq!(gui_api, pub_api);
assert_eq!(gui_api.xmr, 2.0);
assert_eq!(pub_api.xmr, 2.0);
}
#[test]
fn build_p2pool_regex() {
crate::helper::P2poolRegex::new();
use crate::helper::PubP2poolApi;
let mut gui_api = PubP2poolApi::new();
let mut pub_api = PubP2poolApi::new();
pub_api.payouts = 1;
pub_api.payouts_hour = 2.0;
pub_api.payouts_day = 3.0;
pub_api.payouts_month = 4.0;
pub_api.xmr = 1.0;
pub_api.xmr_hour = 2.0;
pub_api.xmr_day = 3.0;
pub_api.xmr_month = 4.0;
println!("BEFORE - GUI_API: {:#?}\nPUB_API: {:#?}", gui_api, pub_api);
assert_ne!(gui_api, pub_api);
PubP2poolApi::combine_gui_pub_api(&mut gui_api, &mut pub_api);
println!("AFTER - GUI_API: {:#?}\nPUB_API: {:#?}", gui_api, pub_api);
assert_eq!(gui_api, pub_api);
pub_api.xmr = 2.0;
PubP2poolApi::combine_gui_pub_api(&mut gui_api, &mut pub_api);
assert_eq!(gui_api, pub_api);
assert_eq!(gui_api.xmr, 2.0);
assert_eq!(pub_api.xmr, 2.0);
}
#[test]
fn calc_payouts_and_xmr_from_output_p2pool() {
use crate::helper::{PubP2poolApi,P2poolRegex};
use crate::helper::{PubP2poolApi};
use std::sync::{Arc,Mutex};
let public = Arc::new(Mutex::new(PubP2poolApi::new()));
let output_parse = Arc::new(Mutex::new(String::from(
@ -1957,9 +1959,8 @@ mod test {
)));
let output_pub = Arc::new(Mutex::new(String::new()));
let elapsed = std::time::Duration::from_secs(60);
let regex = P2poolRegex::new();
let process = Arc::new(Mutex::new(Process::new(ProcessName::P2pool, "".to_string(), PathBuf::new())));
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, &regex, &process);
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, &process);
let public = public.lock().unwrap();
println!("{:#?}", public);
assert_eq!(public.payouts, 3);
@ -1974,7 +1975,7 @@ mod test {
#[test]
fn set_p2pool_synchronized() {
use crate::helper::{PubP2poolApi,P2poolRegex};
use crate::helper::{PubP2poolApi};
use std::sync::{Arc,Mutex};
let public = Arc::new(Mutex::new(PubP2poolApi::new()));
let output_parse = Arc::new(Mutex::new(String::from(
@ -1984,12 +1985,11 @@ mod test {
)));
let output_pub = Arc::new(Mutex::new(String::new()));
let elapsed = std::time::Duration::from_secs(60);
let regex = P2poolRegex::new();
let process = Arc::new(Mutex::new(Process::new(ProcessName::P2pool, "".to_string(), PathBuf::new())));
// It only gets checked if we're `Syncing`.
process.lock().unwrap().state = ProcessState::Syncing;
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, &regex, &process);
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, &process);
println!("{:#?}", process);
assert!(process.lock().unwrap().state == ProcessState::Alive);
}

View file

@ -158,7 +158,6 @@ pub struct App {
version: &'static str, // Gupax version
name_version: String, // [Gupax vX.X.X]
img: Images, // Custom Struct holding pre-compiled bytes of [Images]
regex: Regexes, // Custom Struct holding pre-made [Regex]'s
}
impl App {
@ -264,7 +263,6 @@ impl App {
version: GUPAX_VERSION,
name_version: format!("Gupax {}", GUPAX_VERSION),
img: Images::new(),
regex: Regexes::new(),
};
//---------------------------------------------------------------------------------------------------- App init data that *could* panic
info!("App Init | Getting EXE path...");
@ -839,7 +837,7 @@ fn init_auto(app: &mut App) {
// [Auto-P2Pool]
if app.state.gupax.auto_p2pool {
if !Regexes::addr_ok(&app.regex, &app.state.p2pool.address) {
if !Regexes::addr_ok(&app.state.p2pool.address) {
warn!("Gupax | P2Pool address is not valid! Skipping auto-p2pool...");
} else if !Gupax::path_is_file(&app.state.gupax.p2pool_path) {
warn!("Gupax | P2Pool path is not a file! Skipping auto-p2pool...");
@ -1527,14 +1525,15 @@ impl eframe::App for App {
Alive => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(GREEN))).on_hover_text(P2POOL_ALIVE),
Dead => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(GRAY))).on_hover_text(P2POOL_DEAD),
Failed => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(RED))).on_hover_text(P2POOL_FAILED),
Middle|Waiting => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(YELLOW))).on_hover_text(P2POOL_MIDDLE),
Syncing => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(ORANGE))).on_hover_text(P2POOL_SYNCING),
Middle|Waiting|NotMining => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(YELLOW))).on_hover_text(P2POOL_MIDDLE),
};
ui.separator();
match xmrig_state {
Alive => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(GREEN))).on_hover_text(XMRIG_ALIVE),
Dead => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(GRAY))).on_hover_text(XMRIG_DEAD),
Failed => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(RED))).on_hover_text(XMRIG_FAILED),
NotMining => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(ORANGE))).on_hover_text(XMRIG_NOT_MINING),
Middle|Waiting|Syncing => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(YELLOW))).on_hover_text(XMRIG_MIDDLE),
};
});
@ -1647,7 +1646,7 @@ impl eframe::App for App {
// Check if address is okay before allowing to start.
let mut text = String::new();
let mut ui_enabled = true;
if !Regexes::addr_ok(&self.regex, &self.state.p2pool.address) {
if !Regexes::addr_ok(&self.state.p2pool.address) {
ui_enabled = false;
text = format!("Error: {}", P2POOL_ADDRESS);
} else if !Gupax::path_is_file(&self.state.gupax.p2pool_path) {
@ -1874,11 +1873,11 @@ path_xmr: {:#?}\n
}
Tab::P2pool => {
debug!("App | Entering [P2Pool] Tab");
crate::disk::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.regex, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.width, self.height, ctx, ui);
crate::disk::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.width, self.height, ctx, ui);
}
Tab::Xmrig => {
debug!("App | Entering [XMRig] Tab");
crate::disk::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.regex, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.width, self.height, ctx, ui);
crate::disk::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.width, self.height, ctx, ui);
}
}
});

View file

@ -31,10 +31,13 @@ use egui::{
use std::sync::{Arc,Mutex};
use regex::Regex;
use log::*;
use crate::regex::{
REGEXES,
};
impl crate::disk::P2pool {
#[inline(always)]
pub fn show(&mut self, node_vec: &mut Vec<(String, Node)>, _og: &Arc<Mutex<State>>, ping: &Arc<Mutex<Ping>>, regex: &Regexes, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubP2poolApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
pub fn show(&mut self, node_vec: &mut Vec<(String, Node)>, _og: &Arc<Mutex<State>>, ping: &Arc<Mutex<Ping>>, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubP2poolApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
let text_edit = height / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("P2Pool Tab | Rendering [Console]");
@ -93,7 +96,7 @@ impl crate::disk::P2pool {
if self.address.is_empty() {
text = format!("Monero Address [{}/95] ", len);
color = Color32::LIGHT_GRAY;
} else if Regexes::addr_ok(regex, &self.address) {
} else if Regexes::addr_ok(&self.address) {
text = format!("Monero Address [{}/95] ✔", len);
color = Color32::from_rgb(100, 230, 100);
} else {
@ -248,7 +251,7 @@ impl crate::disk::P2pool {
text = format!("Name [ {}/30 ]", len);
color = Color32::LIGHT_GRAY;
incorrect_input = true;
} else if Regex::is_match(&regex.name, &self.name) {
} else if REGEXES.name.is_match(&self.name) {
text = format!("Name [ {}/30 ]✔", len);
color = Color32::from_rgb(100, 230, 100);
} else {
@ -268,7 +271,7 @@ impl crate::disk::P2pool {
text = format!(" IP [{}/255]", len);
color = Color32::LIGHT_GRAY;
incorrect_input = true;
} else if self.ip == "localhost" || Regex::is_match(&regex.ipv4, &self.ip) || Regex::is_match(&regex.domain, &self.ip) {
} else if self.ip == "localhost" || REGEXES.ipv4.is_match(&self.ip) || REGEXES.domain.is_match(&self.ip) {
text = format!(" IP [{}/255]✔", len);
color = Color32::from_rgb(100, 230, 100);
} else {
@ -288,7 +291,7 @@ impl crate::disk::P2pool {
text = format!(" RPC [ {}/5 ]", len);
color = Color32::LIGHT_GRAY;
incorrect_input = true;
} else if Regex::is_match(&regex.port, &self.rpc) {
} else if REGEXES.port.is_match(&self.rpc) {
text = format!(" RPC [ {}/5 ]✔", len);
color = Color32::from_rgb(100, 230, 100);
} else {
@ -308,7 +311,7 @@ impl crate::disk::P2pool {
text = format!(" ZMQ [ {}/5 ]", len);
color = Color32::LIGHT_GRAY;
incorrect_input = true;
} else if Regex::is_match(&regex.port, &self.zmq) {
} else if REGEXES.port.is_match(&self.zmq) {
text = format!(" ZMQ [ {}/5 ]✔", len);
color = Color32::from_rgb(100, 230, 100);
} else {

View file

@ -18,6 +18,14 @@
// Some regexes used throughout Gupax.
use regex::Regex;
use lazy_static::lazy_static;
//---------------------------------------------------------------------------------------------------- Lazy
lazy_static! {
pub static ref REGEXES: Regexes = Regexes::new();
pub static ref P2POOL_REGEX: P2poolRegex = P2poolRegex::new();
pub static ref XMRIG_REGEX: XmrigRegex = XmrigRegex::new();
}
//---------------------------------------------------------------------------------------------------- [Regexes] struct
// General purpose Regexes, mostly used in the GUI.
@ -31,8 +39,8 @@ pub struct Regexes {
}
impl Regexes {
pub fn new() -> Self {
Regexes {
fn new() -> Self {
Self {
name: Regex::new("^[A-Za-z0-9-_.]+( [A-Za-z0-9-_.]+)*$").unwrap(),
address: Regex::new("^4[A-Za-z1-9]+$").unwrap(), // This still needs to check for (l, I, o, 0)
ipv4: Regex::new(r#"^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$"#).unwrap(),
@ -44,8 +52,8 @@ impl Regexes {
// Check if a Monero address is correct.
// This actually only checks for length & Base58, and doesn't do any checksum validation
// (the last few bytes of a Monero address are a Keccak hash checksum) so some invalid addresses can trick this function.
pub fn addr_ok(&self, address: &str) -> bool {
address.len() == 95 && Regex::is_match(&self.address, address) && !address.contains('0') && !address.contains('O') && !address.contains('l')
pub fn addr_ok(address: &str) -> bool {
address.len() == 95 && REGEXES.address.is_match(address) && !address.contains('0') && !address.contains('O') && !address.contains('l')
}
}
@ -69,25 +77,41 @@ impl Regexes {
// Both are nominally fast enough where it doesn't matter too much but meh, why not use regex.
#[derive(Clone,Debug)]
pub struct P2poolRegex {
pub date: regex::Regex,
pub payout: regex::Regex,
pub payout_float: regex::Regex,
pub block: regex::Regex,
pub block_int: regex::Regex,
pub block_comma: regex::Regex,
pub synchronized: regex::Regex,
pub date: Regex,
pub payout: Regex,
pub payout_float: Regex,
pub block: Regex,
pub block_int: Regex,
pub block_comma: Regex,
pub synchronized: Regex,
}
impl P2poolRegex {
pub fn new() -> Self {
fn new() -> Self {
Self {
date: regex::Regex::new("[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+.[0-9]+").unwrap(),
payout: regex::Regex::new("payout of [0-9].[0-9]+ XMR").unwrap(), // Assumes 12 digits after the dot.
payout_float: regex::Regex::new("[0-9].[0-9]{12}").unwrap(), // Assumes 12 digits after the dot.
block: regex::Regex::new("block [0-9]{7}").unwrap(), // Monero blocks will be 7 digits for... the next 10,379 years
block_int: regex::Regex::new("[0-9]{7}").unwrap(),
block_comma: regex::Regex::new("[0-9],[0-9]{3},[0-9]{3}").unwrap(),
synchronized: regex::Regex::new("SYNCHRONIZED").unwrap(),
date: Regex::new("[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+.[0-9]+").unwrap(),
payout: Regex::new("payout of [0-9].[0-9]+ XMR").unwrap(), // Assumes 12 digits after the dot.
payout_float: Regex::new("[0-9].[0-9]{12}").unwrap(), // Assumes 12 digits after the dot.
block: Regex::new("block [0-9]{7}").unwrap(), // Monero blocks will be 7 digits for... the next 10,379 years
block_int: Regex::new("[0-9]{7}").unwrap(),
block_comma: Regex::new("[0-9],[0-9]{3},[0-9]{3}").unwrap(),
synchronized: Regex::new("SYNCHRONIZED").unwrap(),
}
}
}
//---------------------------------------------------------------------------------------------------- XMRig regex.
#[derive(Debug)]
pub struct XmrigRegex {
not_mining: Regex,
mining: Regex,
}
impl XmrigRegex {
fn new() -> Self {
Self {
not_mining: Regex::new("no active pools, stop mining").unwrap(),
mining: Regex::new("new job").unwrap(),
}
}
}

View file

@ -24,7 +24,9 @@
use crate::{
human::*,
P2poolRegex,
};
use crate::regex::{
P2POOL_REGEX,
};
use log::*;
@ -141,15 +143,15 @@ impl PayoutOrd {
}
// Expected input: "NOTICE 2022-01-27 01:30:23.1377 P2Pool You received a payout of 0.000000000001 XMR in block 2642816"
pub fn parse_raw_payout_line(line: &str, regex: &P2poolRegex) -> (String, AtomicUnit, HumanNumber) {
pub fn parse_raw_payout_line(line: &str) -> (String, AtomicUnit, HumanNumber) {
// Date
let date = match regex.date.find(line) {
let date = match P2POOL_REGEX.date.find(line) {
Some(date) => date.as_str().to_string(),
None => { error!("P2Pool | Date parse error: [{}]", line); "????-??-?? ??:??:??.????".to_string() },
};
// AtomicUnit
let atomic_unit = if let Some(word) = regex.payout.find(line) {
if let Some(word) = regex.payout_float.find(word.as_str()) {
let atomic_unit = if let Some(word) = P2POOL_REGEX.payout.find(line) {
if let Some(word) = P2POOL_REGEX.payout_float.find(word.as_str()) {
match word.as_str().parse::<f64>() {
Ok(au) => AtomicUnit::from_f64(au),
Err(e) => { error!("P2Pool | AtomicUnit parse error: [{}] on [{}]", e, line); AtomicUnit::new() },
@ -163,8 +165,8 @@ impl PayoutOrd {
AtomicUnit::new()
};
// Block
let block = if let Some(word) = regex.block.find(line) {
if let Some(word) = regex.block_int.find(word.as_str()) {
let block = if let Some(word) = P2POOL_REGEX.block.find(line) {
if let Some(word) = P2POOL_REGEX.block_int.find(word.as_str()) {
match word.as_str().parse::<u64>() {
Ok(b) => HumanNumber::from_u64(b),
Err(e) => { error!("P2Pool | Block parse error: [{}] on [{}]", e, line); HumanNumber::unknown() },
@ -181,14 +183,14 @@ impl PayoutOrd {
}
// Expected input: "2022-01-27 01:30:23.1377 | 0.000000000001 XMR | Block 2,642,816"
pub fn parse_formatted_payout_line(line: &str, regex: &P2poolRegex) -> (String, AtomicUnit, HumanNumber) {
pub fn parse_formatted_payout_line(line: &str) -> (String, AtomicUnit, HumanNumber) {
// Date
let date = match regex.date.find(line) {
let date = match P2POOL_REGEX.date.find(line) {
Some(date) => date.as_str().to_string(),
None => { error!("P2Pool | Date parse error: [{}]", line); "????-??-?? ??:??:??.????".to_string() },
};
// AtomicUnit
let atomic_unit = if let Some(word) = regex.payout_float.find(line) {
let atomic_unit = if let Some(word) = P2POOL_REGEX.payout_float.find(line) {
match word.as_str().parse::<f64>() {
Ok(au) => AtomicUnit::from_f64(au),
Err(e) => { error!("P2Pool | AtomicUnit parse error: [{}] on [{}]", e, line); AtomicUnit::new() },
@ -198,7 +200,7 @@ impl PayoutOrd {
AtomicUnit::new()
};
// Block
let block = match regex.block_comma.find(line) {
let block = match P2POOL_REGEX.block_comma.find(line) {
Some(b) => HumanNumber::from_str(b.as_str()),
None => { error!("P2Pool | Block parse error: [{}]", line); HumanNumber::unknown() },
};
@ -215,12 +217,11 @@ impl PayoutOrd {
// Spaces, pipes, commas and words (XMR, Block): [19]
// Add 7 more bytes for wrapper type overhead and it's an even [70] bytes per line.
pub fn update_from_payout_log(&mut self, log: &str) {
let regex = P2poolRegex::new();
let amount_of_lines = log.lines().count();
let mut vec: Vec<(String, AtomicUnit, HumanNumber)> = Vec::with_capacity(70 * amount_of_lines);
for line in log.lines() {
debug!("PayoutOrd | Parsing line: [{}]", line);
vec.push(Self::parse_formatted_payout_line(line, &regex));
vec.push(Self::parse_formatted_payout_line(line));
}
*self = Self(vec);
}

View file

@ -32,10 +32,13 @@ use std::{
};
use regex::Regex;
use log::*;
use crate::regex::{
REGEXES,
};
impl crate::disk::Xmrig {
#[inline(always)]
pub fn show(&mut self, pool_vec: &mut Vec<(String, Pool)>, regex: &Regexes, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubXmrigApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
pub fn show(&mut self, pool_vec: &mut Vec<(String, Pool)>, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubXmrigApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
let text_edit = height / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("XMRig Tab | Rendering [Console]");
@ -92,7 +95,7 @@ impl crate::disk::Xmrig {
if self.address.is_empty() {
text = format!("Monero Address [{}/95] ", len);
color = LIGHT_GRAY;
} else if self.address.len() == 95 && Regex::is_match(&regex.address, &self.address) && ! self.address.contains('0') && ! self.address.contains('O') && ! self.address.contains('l') {
} else if Regexes::addr_ok(&self.address) {
text = format!("Monero Address [{}/95] ✔", len);
color = GREEN;
} else {
@ -147,7 +150,7 @@ impl crate::disk::Xmrig {
text = format!("Name [ {}/30 ]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if Regex::is_match(&regex.name, &self.name) {
} else if REGEXES.name.is_match(&self.name) {
text = format!("Name [ {}/30 ]✔", len);
color = GREEN;
} else {
@ -167,7 +170,7 @@ impl crate::disk::Xmrig {
text = format!(" IP [{}/255]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if self.ip == "localhost" || Regex::is_match(&regex.ipv4, &self.ip) || Regex::is_match(&regex.domain, &self.ip) {
} else if self.ip == "localhost" || REGEXES.ipv4.is_match(&self.ip) || REGEXES.domain.is_match(&self.ip) {
text = format!(" IP [{}/255]✔", len);
color = GREEN;
} else {
@ -187,7 +190,7 @@ impl crate::disk::Xmrig {
text = format!("Port [ {}/5 ]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if Regex::is_match(&regex.port, &self.port) {
} else if REGEXES.port.is_match(&self.port) {
text = format!("Port [ {}/5 ]✔", len);
color = GREEN;
} else {
@ -206,7 +209,7 @@ impl crate::disk::Xmrig {
if self.rig.is_empty() {
text = format!(" Rig [ {}/30 ]", len);
color = LIGHT_GRAY;
} else if Regex::is_match(&regex.name, &self.rig) {
} else if REGEXES.name.is_match(&self.rig) {
text = format!(" Rig [ {}/30 ]✔", len);
color = GREEN;
} else {
@ -361,7 +364,7 @@ impl crate::disk::Xmrig {
text = format!("HTTP API IP [{}/255]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if self.api_ip == "localhost" || Regex::is_match(&regex.ipv4, &self.api_ip) || Regex::is_match(&regex.domain, &self.api_ip) {
} else if self.api_ip == "localhost" || REGEXES.ipv4.is_match(&self.api_ip) || REGEXES.domain.is_match(&self.api_ip) {
text = format!("HTTP API IP [{}/255]✔", len);
color = GREEN;
} else {
@ -381,7 +384,7 @@ impl crate::disk::Xmrig {
text = format!("HTTP API Port [ {}/5 ]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if Regex::is_match(&regex.port, &self.api_port) {
} else if REGEXES.port.is_match(&self.api_port) {
text = format!("HTTP API Port [ {}/5 ]✔", len);
color = GREEN;
} else {