#![warn(missing_docs)]
pub mod debug {
use tracing::{enabled, trace};
pub fn log_buffer(message: &str, buf: &[u8]) {
if !enabled!(target: "hex", tracing::Level::TRACE) {
return;
}
let line_len = 32;
let len = buf.len();
let last_line_padding = ((len / line_len) + 1) * line_len - len;
trace!(target: "hex", "{}", message);
let mut char_line = String::new();
let mut hex_line = format!("{:08x}: ", 0);
for (i, b) in buf.iter().enumerate() {
let value = { *b };
if i > 0 && i % line_len == 0 {
trace!(target: "hex", "{} {}", hex_line, char_line);
hex_line = format!("{i:08}: ");
char_line.clear();
}
hex_line = format!("{hex_line} {value:02x}");
char_line.push(if (32..=126).contains(&value) {
value as char
} else {
'.'
});
}
if last_line_padding > 0 {
for _ in 0..last_line_padding {
hex_line.push_str(" ");
}
trace!(target: "hex", "{} {}", hex_line, char_line);
}
}
}
#[cfg(test)]
pub(crate) mod tests;
pub mod constants {
pub const DEFAULT_OPC_UA_SERVER_PORT: u16 = 4840;
}
pub mod comms;
pub mod config;
pub mod handle;
pub mod messages;
use std::sync::atomic::AtomicBool;
pub use messages::{Message, MessageType, RequestMessage, ResponseMessage};
pub fn trace_locks() -> bool {
static ENABLED: AtomicBool = AtomicBool::new(false);
if ENABLED.load(std::sync::atomic::Ordering::Relaxed) {
return true;
}
let enabled = match std::env::var("OPCUA_TRACE_LOCKS") {
Ok(s) => s != "0",
Err(_) => false,
};
ENABLED.store(enabled, std::sync::atomic::Ordering::Relaxed);
enabled
}
pub use tracing;
#[macro_export]
macro_rules! trace_lock {
( $x:expr ) => {{
use std::thread;
if $crate::trace_locks() {
$crate::tracing::trace!(
"Thread {:?}, {} locking at {}, line {}",
thread::current().id(),
stringify!($x),
file!(),
line!()
);
}
let v = $x.lock();
if $crate::trace_locks() {
$crate::tracing::trace!(
"Thread {:?}, {} lock completed",
thread::current().id(),
stringify!($x)
);
}
v
}};
}
#[macro_export]
macro_rules! trace_read_lock {
( $x:expr ) => {{
use std::thread;
if $crate::trace_locks() {
$crate::tracing::trace!(
"Thread {:?}, {} read locking at {}, line {}",
thread::current().id(),
stringify!($x),
file!(),
line!()
);
}
let v = $x.read();
if $crate::trace_locks() {
$crate::tracing::trace!(
"Thread {:?}, {} read lock completed",
thread::current().id(),
stringify!($x)
);
}
v
}};
}
#[macro_export]
macro_rules! trace_write_lock {
( $x:expr ) => {{
use std::thread;
if $crate::trace_locks() {
$crate::tracing::trace!(
"Thread {:?}, {} write locking at {}, line {}",
thread::current().id(),
stringify!($x),
file!(),
line!()
);
}
let v = $x.write();
if $crate::trace_locks() {
$crate::tracing::trace!(
"Thread {:?}, {} write lock completed",
thread::current().id(),
stringify!($x)
);
}
v
}};
}
pub mod sync {
pub type RwLock<T> = parking_lot::RwLock<T>;
pub type Mutex<T> = parking_lot::Mutex<T>;
}