summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-07-16 11:28:09 +0200
committerJustus Winter <justus@sequoia-pgp.org>2021-07-16 11:57:26 +0200
commit67274203bb852749c420f0ef7fd7dec8d55ef4ef (patch)
treef0cb2814f95af9b256da05dfd91bbfe3e5b9b3ee /ipc
parent9772cb922c0c5bd406a5572df380b84a0d0f11f5 (diff)
ipc: Bring in our bag of macros.
Diffstat (limited to 'ipc')
-rw-r--r--ipc/src/lib.rs2
-rw-r--r--ipc/src/macros.rs177
-rw-r--r--ipc/src/trace.rs63
3 files changed, 178 insertions, 64 deletions
diff --git a/ipc/src/lib.rs b/ipc/src/lib.rs
index 10b1b563..9cb0fe1f 100644
--- a/ipc/src/lib.rs
+++ b/ipc/src/lib.rs
@@ -65,7 +65,7 @@ use std::thread;
use sequoia_openpgp as openpgp;
-#[macro_use] mod trace;
+#[macro_use] mod macros;
pub mod assuan;
pub mod gnupg;
pub mod keybox;
diff --git a/ipc/src/macros.rs b/ipc/src/macros.rs
new file mode 100644
index 00000000..18ace037
--- /dev/null
+++ b/ipc/src/macros.rs
@@ -0,0 +1,177 @@
+use std::cmp;
+
+macro_rules! trace {
+ ( $TRACE:expr, $fmt:expr, $($pargs:expr),* ) => {
+ if $TRACE {
+ eprintln!($fmt, $($pargs),*);
+ }
+ };
+ ( $TRACE:expr, $fmt:expr ) => {
+ trace!($TRACE, $fmt, );
+ };
+}
+
+// Converts an indentation level to whitespace.
+pub(crate) fn indent(i: isize) -> &'static str {
+ use std::convert::TryFrom;
+ let s = " ";
+ &s[0..cmp::min(usize::try_from(i).unwrap_or(0), s.len())]
+}
+
+macro_rules! tracer {
+ ( $TRACE:expr, $func:expr ) => {
+ tracer!($TRACE, $func, 0)
+ };
+ ( $TRACE:expr, $func:expr, $indent:expr ) => {
+ // Currently, Rust doesn't support $( ... ) in a nested
+ // macro's definition. See:
+ // https://users.rust-lang.org/t/nested-macros-issue/8348/2
+ macro_rules! t {
+ ( $fmt:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, $fmt) };
+ ( $fmt:expr, $a:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a)) };
+ ( $fmt:expr, $a:expr, $b:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c, $d)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c, $d, $e)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c, $d, $e, $f)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g, $h)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $i:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g, $h, $i)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $i:expr, $j:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j)) };
+ ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $i:expr, $j:expr, $k:expr ) =>
+ { trace!($TRACE, "{}{}: {}", crate::macros::indent($indent), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k)) };
+ }
+ }
+}
+
+
+/// A very simple profiling tool.
+///
+/// Note: don't ever profile code that has not been compiled in
+/// release mode. There can be orders of magnitude difference in
+/// execution time between it and debug mode!
+///
+/// This macro measures the wall time it takes to execute the block.
+/// If the time is at least $ms_threshold (in milli-seconds), then it
+/// displays the output on stderr. The output is prefixed with label,
+/// if it is provided.
+///
+/// ```
+/// let result = time_it!("Some code", 10, {
+/// // Some code.
+/// 5
+/// });
+/// assert_eq!(result, 5);
+/// ```
+#[allow(unused_macros)]
+macro_rules! time_it {
+ ( $label:expr, $ms_threshold:expr, $body:expr ) => {{
+ use std::time::{SystemTime, Duration};
+
+ // We use drop so that code that uses non-local exits (e.g.,
+ // using break 'label) still works.
+ struct Timer {
+ start: SystemTime,
+ };
+ impl Drop for Timer {
+ fn drop(&mut self) {
+ let elapsed = self.start.elapsed();
+ if elapsed.clone().unwrap_or(Duration::from_millis($ms_threshold))
+ >= Duration::from_millis($ms_threshold)
+ {
+ if $label.len() > 0 {
+ eprint!("{}:", $label);
+ }
+ eprintln!("{}:{}: {:?}", file!(), line!(), elapsed);
+ }
+ }
+ }
+
+ let _start = Timer { start: SystemTime::now() };
+ $body
+ }};
+ ( $label:expr, $body:expr ) => {
+ time_it!($label, 0, $body)
+ };
+ ( $body:expr ) => {
+ time_it!("", $body)
+ };
+}
+
+/// A simple shortcut for ensuring a type is send and sync.
+///
+/// For most types just call it after defining the type:
+///
+/// ```
+/// pub struct MyStruct {}
+/// assert_send_and_sync!(MyStruct);
+/// ```
+///
+/// For types with lifetimes, use the anonymous lifetime:
+///
+/// ```
+/// pub struct WithLifetime<'a> {}
+/// assert_send_and_sync!(MyStruct<'_>);
+/// ```
+///
+/// For a type generic over another type `W`,
+/// pass the type `W` as a where clause
+/// including a trait bound when needed:
+///
+/// ```
+/// pub struct MyWriter<W: io::Write> {}
+/// assert_send_and_sync!(MyWriterStruct<W> where W: io::Write);
+/// ```
+///
+/// This will assert that `MyWriterStruct<W>` is `Send` and `Sync`
+/// if `W` is `Send` and `Sync`.
+///
+/// You can also combine the two and be generic over multiple types.
+/// Just make sure to list all the types - even those without additional
+/// trait bounds:
+///
+/// ```
+/// pub struct MyWriterWithLifetime<a', C, W: io::Write> {}
+/// assert_send_and_sync!(MyWriterStruct<'_, C, W> where C, W: io::Write);
+/// ```
+///
+/// If you need multiple additional trait bounds on a single type
+/// you can add them separated by `+` like in normal where clauses.
+/// However you have to make sure they are `Identifiers` like `Write`.
+/// In macro patterns `Paths` (like `io::Write`) may not be followed
+/// by `+` characters.
+macro_rules! assert_send_and_sync {
+ ( $x:ty where $( $g:ident$( : $a:path )? $(,)?)*) => {
+ impl<$( $g ),*> crate::types::Sendable for $x
+ where $( $g: Send + Sync $( + $a )? ),*
+ {}
+ impl<$( $g ),*> crate::types::Syncable for $x
+ where $( $g: Send + Sync $( + $a )? ),*
+ {}
+ };
+ ( $x:ty where $( $g:ident$( : $a:ident $( + $b:ident )* )? $(,)?)*) => {
+ impl<$( $g ),*> crate::types::Sendable for $x
+ where $( $g: Send + Sync $( + $a $( + $b )* )? ),*
+ {}
+ impl<$( $g ),*> crate::types::Syncable for $x
+ where $( $g: Send + Sync $( + $a $( + $b )* )? ),*
+ {}
+ };
+ ( $x:ty ) => {
+ impl crate::macros::Sendable for $x {}
+ impl crate::macros::Syncable for $x {}
+ };
+}
+pub(crate) trait Sendable : Send {}
+pub(crate) trait Syncable : Sync {}
diff --git a/ipc/src/trace.rs b/ipc/src/trace.rs
deleted file mode 100644
index c93e1e04..00000000
--- a/ipc/src/trace.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use std::cmp;
-
-macro_rules! trace {
- ( $TRACE:expr, $fmt:expr, $($pargs:expr),* ) => {
- if $TRACE {
- eprintln!($fmt, $($pargs),*);
- }
- };
- ( $TRACE:expr, $fmt:expr ) => {
- trace!($TRACE, $fmt, );
- };
-}
-
-// Converts an indentation level to whitespace.
-pub(crate) fn indent(i: usize) -> &'static str {
- let s = " ";
- &s[0..cmp::min(i, s.len())]
-}
-
-// A very simply tracer.
-//
-// ```text
-// tracer!(enable_predicate, "function_name");
-// t!("(arg1: {:?}, arg2: {:?})", arg1, arg2);
-// ...
-// t!("=> {:?}", return_value);
-// ```
-macro_rules! tracer {
- ( $TRACE:expr, $func:expr ) => {
- tracer!($TRACE, $func, 0)
- };
- ( $TRACE:expr, $func:expr, $indent:expr ) => {
- // Currently, Rust doesn't support $( ... ) in a nested
- // macro's definition. See:
- // https://users.rust-lang.org/t/nested-macros-issue/8348/2
- macro_rules! t {
- ( $fmt:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, $fmt) };
- ( $fmt:expr, $a:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a)) };
- ( $fmt:expr, $a:expr, $b:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c, $d)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c, $d, $e)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c, $d, $e, $f)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g, $h)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $i:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g, $h, $i)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $i:expr, $j:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j)) };
- ( $fmt:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $i:expr, $j:expr, $k:expr ) =>
- { trace!($TRACE, "{}{}: {}", crate::trace::indent($indent as usize), $func, format!($fmt, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k)) };
- }
- };
-}