1#![warn(missing_docs)]
6
7pub mod debug {
12 use tracing::{enabled, trace};
13
14 pub fn log_buffer(message: &str, buf: &[u8]) {
17 if !enabled!(target: "hex", tracing::Level::TRACE) {
19 return;
20 }
21
22 let line_len = 32;
23 let len = buf.len();
24 let last_line_padding = ((len / line_len) + 1) * line_len - len;
25
26 trace!(target: "hex", "{}", message);
27
28 let mut char_line = String::new();
29 let mut hex_line = format!("{:08x}: ", 0);
30
31 for (i, b) in buf.iter().enumerate() {
32 let value = { *b };
33 if i > 0 && i % line_len == 0 {
34 trace!(target: "hex", "{} {}", hex_line, char_line);
35 hex_line = format!("{i:08}: ");
36 char_line.clear();
37 }
38 hex_line = format!("{hex_line} {value:02x}");
39 char_line.push(if (32..=126).contains(&value) {
40 value as char
41 } else {
42 '.'
43 });
44 }
45 if last_line_padding > 0 {
46 for _ in 0..last_line_padding {
47 hex_line.push_str(" ");
48 }
49 trace!(target: "hex", "{} {}", hex_line, char_line);
50 }
51 }
52}
53
54#[cfg(test)]
55pub(crate) mod tests;
56
57pub mod constants {
59 pub const DEFAULT_OPC_UA_SERVER_PORT: u16 = 4840;
63}
64
65pub mod comms;
66pub mod config;
67pub mod handle;
68
69pub mod messages;
70use std::sync::atomic::AtomicBool;
71
72pub use messages::{Message, MessageType, RequestMessage, ResponseMessage};
73
74pub fn trace_locks() -> bool {
77 static ENABLED: AtomicBool = AtomicBool::new(false);
78 if ENABLED.load(std::sync::atomic::Ordering::Relaxed) {
79 return true;
80 }
81 let enabled = match std::env::var("OPCUA_TRACE_LOCKS") {
82 Ok(s) => s != "0",
83 Err(_) => false,
84 };
85
86 ENABLED.store(enabled, std::sync::atomic::Ordering::Relaxed);
87
88 enabled
89}
90pub use tracing;
92
93#[macro_export]
96macro_rules! trace_lock {
97 ( $x:expr ) => {{
98 use std::thread;
99 if $crate::trace_locks() {
100 $crate::tracing::trace!(
101 "Thread {:?}, {} locking at {}, line {}",
102 thread::current().id(),
103 stringify!($x),
104 file!(),
105 line!()
106 );
107 }
108 let v = $x.lock();
109 if $crate::trace_locks() {
110 $crate::tracing::trace!(
111 "Thread {:?}, {} lock completed",
112 thread::current().id(),
113 stringify!($x)
114 );
115 }
116 v
117 }};
118}
119
120#[macro_export]
122macro_rules! trace_read_lock {
123 ( $x:expr ) => {{
124 use std::thread;
125 if $crate::trace_locks() {
126 $crate::tracing::trace!(
127 "Thread {:?}, {} read locking at {}, line {}",
128 thread::current().id(),
129 stringify!($x),
130 file!(),
131 line!()
132 );
133 }
134 let v = $x.read();
135 if $crate::trace_locks() {
136 $crate::tracing::trace!(
137 "Thread {:?}, {} read lock completed",
138 thread::current().id(),
139 stringify!($x)
140 );
141 }
142 v
143 }};
144}
145
146#[macro_export]
148macro_rules! trace_write_lock {
149 ( $x:expr ) => {{
150 use std::thread;
151 if $crate::trace_locks() {
152 $crate::tracing::trace!(
153 "Thread {:?}, {} write locking at {}, line {}",
154 thread::current().id(),
155 stringify!($x),
156 file!(),
157 line!()
158 );
159 }
160 let v = $x.write();
161 if $crate::trace_locks() {
162 $crate::tracing::trace!(
163 "Thread {:?}, {} write lock completed",
164 thread::current().id(),
165 stringify!($x)
166 );
167 }
168 v
169 }};
170}
171
172pub mod sync {
174 pub type RwLock<T> = parking_lot::RwLock<T>;
176 pub type Mutex<T> = parking_lot::Mutex<T>;
178}