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
use std::process;
use crate::error::CuidError;
use crate::text::{pad, to_base_string};
use crate::BASE;
static FINGERPRINT_PADDING: usize = 2;
fn pid() -> Result<String, CuidError> {
to_base_string(process::id())
.map(|s| pad(FINGERPRINT_PADDING, s))
.map_err(|_| CuidError::FingerprintError("Could not encode pid"))
}
fn convert_hostname(hn: &str) -> Result<String, CuidError> {
to_base_string(
hn.chars()
.fold(hn.len() + BASE as usize, |acc, c| acc + c as usize) as u64,
)
.map(|base_str| pad(FINGERPRINT_PADDING, base_str))
}
fn host_id() -> Result<String, CuidError> {
let hn = hostname::get()?;
convert_hostname(&hn.to_string_lossy())
}
pub fn fingerprint() -> Result<String, CuidError> {
let mut hid = host_id()?;
let procid = pid()?;
hid.push_str(&procid);
Ok(hid)
}
#[cfg(test)]
mod fingerprint_tests {
use super::*;
#[test]
fn test_pid_length() {
assert_eq!(pid().unwrap().len(), FINGERPRINT_PADDING)
}
#[test]
fn test_convert_hostname_1() {
assert_eq!("a3", &*convert_hostname("foo").unwrap())
}
#[test]
fn test_convert_hostname_2() {
assert_eq!("9o", &*convert_hostname("bar").unwrap())
}
#[test]
fn test_convert_hostname_3() {
assert_eq!("nf", &*convert_hostname("mr-magoo").unwrap())
}
#[test]
fn test_convert_hostname_4() {
assert_eq!(
"j9",
&*convert_hostname("wow-what-a-long-hostname-you-have").unwrap()
)
}
#[test]
fn fingerprint_len() {
assert_eq!(4, fingerprint().unwrap().len())
}
}
#[cfg(nightly)]
#[cfg(test)]
mod benchmarks {
use super::*;
use test::Bencher;
#[bench]
fn bench_pid(b: &mut Bencher) {
b.iter(|| {
pid().unwrap();
})
}
#[bench]
fn bench_convert_hostname_real(b: &mut Bencher) {
b.iter(|| {
convert_hostname(get_hostname).unwrap();
})
}
#[bench]
fn bench_convert_hostname_mock(b: &mut Bencher) {
b.iter(|| {
convert_hostname(|| Some(String::from("hostname"))).unwrap();
})
}
#[bench]
fn bench_fingerprint(b: &mut Bencher) {
b.iter(|| {
fingerprint().unwrap();
})
}
}