1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! The domain model of Samotop and core functionality. A base crate for samotop extensions.

#[macro_use]
extern crate log;

pub mod io;
pub mod mail;
pub mod smtp;

#[cfg(feature = "server")]
pub mod server;

pub mod common {
    pub type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
    pub type Result<T> = std::result::Result<T, Error>;
    pub mod io {
        pub use futures_io::{
            AsyncBufRead as BufRead, AsyncRead as Read, AsyncSeek as Seek, AsyncWrite as Write,
        };
        pub use std::io::{Error, ErrorKind, Result};
    }
    //pub use async_std::io;
    //pub use async_std::io::prelude::{ReadExt, WriteExt};
    //pub use async_std::io::{Read, Write};
    pub use futures_core::ready;
    use std::any::TypeId;
    pub use std::future::*;
    pub type S3Fut<T> = Pin<Box<dyn Future<Output = T> + Sync + Send + 'static>>;
    pub type S2Fut<'a, T> = Pin<Box<dyn Future<Output = T> + Sync + Send + 'a>>;
    pub type S1Fut<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
    pub use std::fmt;
    pub use std::pin::Pin;
    use std::sync::atomic::AtomicU32;
    use std::sync::atomic::Ordering;
    pub use std::sync::Arc;
    pub use std::task::{Context, Poll};

    #[derive(Debug, Copy, Clone)]
    pub struct Dummy;

    // pub async fn ready<T>(val: T) -> T {
    //     val
    // }

    // replace with std once stable - use of unstable library feature 'future_poll_fn'
    pub async fn poll_fn<F, T>(f: F) -> T
    where
        F: FnMut(&mut Context<'_>) -> Poll<T>,
    {
        let fut = PollFn { f };
        fut.await
    }

    struct PollFn<F> {
        f: F,
    }

    impl<F> Unpin for PollFn<F> {}

    impl<T, F> Future for PollFn<F>
    where
        F: FnMut(&mut Context<'_>) -> Poll<T>,
    {
        type Output = T;

        fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
            (&mut self.f)(cx)
        }
    }

    /// In the absence of random number generator produces a time based identifier
    /// It is not reliable nor secure, RNG/PRNG should be preffered.
    #[deprecated(
        since = "0.13.1",
        note = "Use Identify::now() instead. This shall be removed in 0.14.0"
    )]
    pub fn time_based_id() -> String {
        Identify::now().to_string()
    }

    pub struct Identify;
    impl Identify {
        pub fn instance() -> u32 {
            static INSTANCE: AtomicU32 = AtomicU32::new(0);
            // CHECKME: what about all these Ordering styles?
            let mut value = INSTANCE.load(Ordering::Relaxed);
            if value == 0 {
                value = Self::now();
                match INSTANCE.compare_exchange(0, value, Ordering::Relaxed, Ordering::Relaxed) {
                    Ok(_) => value,
                    Err(value) => value,
                }
            } else {
                value
            }
        }
        pub fn now() -> u32 {
            // for the lack of better unique string without extra dependencies
            Self::hash(
                format!(
                    "{}.{}.{:?}.{:?}",
                    env!("CARGO_PKG_VERSION"),
                    std::process::id(),
                    std::time::Instant::now(),
                    TypeId::of::<crate::smtp::SmtpSession>()
                )
                .as_str(),
            )
        }
        const fn hash(s: &str) -> u32 {
            let s = s.as_bytes();
            let mut hash = 3581u32;
            let mut i = 0usize;
            while i < s.len() {
                hash = hash.wrapping_mul(33).wrapping_add(s[i] as u32);
                i += 1;
            }
            hash
        }
    }
}

#[test]
fn identify_instance_is_not_zero() {
    assert_ne!(common::Identify::instance(), 0)
}
#[test]
fn identify_instance_stays_constant() {
    assert_eq!(common::Identify::instance(), common::Identify::instance())
}
#[test]
fn identify_now_is_not_zero() {
    assert_ne!(common::Identify::now(), 0)
}
#[test]
fn identify_now_is_unique() {
    assert_ne!(common::Identify::now(), common::Identify::now())
}