fxa_client/internal/
util.rs
1use crate::{Error, Result};
6use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
7use rc_crypto::rand;
8use std::time::{SystemTime, UNIX_EPOCH};
9
10pub fn now() -> u64 {
12 let since_epoch = SystemTime::now()
13 .duration_since(UNIX_EPOCH)
14 .expect("Something is very wrong.");
15 since_epoch.as_secs() * 1000 + u64::from(since_epoch.subsec_nanos()) / 1_000_000
16}
17
18pub fn now_secs() -> u64 {
19 let since_epoch = SystemTime::now()
20 .duration_since(UNIX_EPOCH)
21 .expect("Something is very wrong.");
22 since_epoch.as_secs()
23}
24
25pub fn past_timestamp(days: u64) -> u64 {
27 now() - (1000 * 60 * 60 * 24 * days)
29}
30
31pub fn random_base64_url_string(len: usize) -> Result<String> {
32 let mut out = vec![0u8; len];
33 rand::fill(&mut out)?;
34 Ok(URL_SAFE_NO_PAD.encode(&out))
35}
36
37pub trait Xorable {
38 #[allow(dead_code)]
39 fn xored_with(&self, other: &[u8]) -> Result<Vec<u8>>;
40}
41
42impl Xorable for [u8] {
43 fn xored_with(&self, other: &[u8]) -> Result<Vec<u8>> {
44 if self.len() != other.len() {
45 Err(Error::XorLengthMismatch(self.len(), other.len()))
46 } else {
47 Ok(self
48 .iter()
49 .zip(other.iter())
50 .map(|(&x, &y)| x ^ y)
51 .collect())
52 }
53 }
54}