1#[macro_use]
4extern crate log;
5
6pub mod io;
7pub mod mail;
8pub mod smtp;
9
10#[cfg(feature = "server")]
11pub mod server;
12
13pub mod common {
14 pub type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
15 pub type Result<T> = std::result::Result<T, Error>;
16 pub mod io {
17 pub use futures_io::{
18 AsyncBufRead as BufRead, AsyncRead as Read, AsyncSeek as Seek, AsyncWrite as Write,
19 };
20 pub use std::io::{Error, ErrorKind, Result};
21 }
22 pub use futures_core::ready;
26 use std::any::TypeId;
27 pub use std::future::*;
28 pub type S3Fut<T> = Pin<Box<dyn Future<Output = T> + Sync + Send + 'static>>;
29 pub type S2Fut<'a, T> = Pin<Box<dyn Future<Output = T> + Sync + Send + 'a>>;
30 pub type S1Fut<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
31 pub use std::fmt;
32 pub use std::pin::Pin;
33 use std::sync::atomic::AtomicU32;
34 use std::sync::atomic::Ordering;
35 pub use std::sync::Arc;
36 pub use std::task::{Context, Poll};
37
38 #[derive(Debug, Copy, Clone)]
39 pub struct Dummy;
40
41 pub async fn poll_fn<F, T>(f: F) -> T
47 where
48 F: FnMut(&mut Context<'_>) -> Poll<T>,
49 {
50 let fut = PollFn { f };
51 fut.await
52 }
53
54 struct PollFn<F> {
55 f: F,
56 }
57
58 impl<F> Unpin for PollFn<F> {}
59
60 impl<T, F> Future for PollFn<F>
61 where
62 F: FnMut(&mut Context<'_>) -> Poll<T>,
63 {
64 type Output = T;
65
66 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
67 (&mut self.f)(cx)
68 }
69 }
70
71 #[deprecated(
74 since = "0.13.1",
75 note = "Use Identify::now() instead. This shall be removed in 0.14.0"
76 )]
77 pub fn time_based_id() -> String {
78 Identify::now().to_string()
79 }
80
81 pub struct Identify;
82 impl Identify {
83 pub fn instance() -> u32 {
84 static INSTANCE: AtomicU32 = AtomicU32::new(0);
85 let mut value = INSTANCE.load(Ordering::Relaxed);
87 if value == 0 {
88 value = Self::now();
89 match INSTANCE.compare_exchange(0, value, Ordering::Relaxed, Ordering::Relaxed) {
90 Ok(_) => value,
91 Err(value) => value,
92 }
93 } else {
94 value
95 }
96 }
97 pub fn now() -> u32 {
98 Self::hash(
100 format!(
101 "{}.{}.{:?}.{:?}",
102 env!("CARGO_PKG_VERSION"),
103 std::process::id(),
104 std::time::Instant::now(),
105 TypeId::of::<crate::smtp::SmtpSession>()
106 )
107 .as_str(),
108 )
109 }
110 const fn hash(s: &str) -> u32 {
111 let s = s.as_bytes();
112 let mut hash = 3581u32;
113 let mut i = 0usize;
114 while i < s.len() {
115 hash = hash.wrapping_mul(33).wrapping_add(s[i] as u32);
116 i += 1;
117 }
118 hash
119 }
120 }
121}
122
123#[test]
124fn identify_instance_is_not_zero() {
125 assert_ne!(common::Identify::instance(), 0)
126}
127#[test]
128fn identify_instance_stays_constant() {
129 assert_eq!(common::Identify::instance(), common::Identify::instance())
130}
131#[test]
132fn identify_now_is_not_zero() {
133 assert_ne!(common::Identify::now(), 0)
134}
135#[test]
136fn identify_now_is_unique() {
137 assert_ne!(common::Identify::now(), common::Identify::now())
138}