2024-05-27 20:05:33 +00:00
|
|
|
pub mod content_disposition;
|
|
|
|
pub mod debug;
|
|
|
|
pub mod defer;
|
2024-06-04 23:51:02 +00:00
|
|
|
pub mod hash;
|
2024-05-27 20:05:33 +00:00
|
|
|
pub mod html;
|
|
|
|
pub mod json;
|
|
|
|
pub mod sys;
|
|
|
|
|
2023-12-25 16:28:56 +01:00
|
|
|
use std::{
|
2024-03-29 18:28:04 -07:00
|
|
|
cmp,
|
2023-12-25 16:28:56 +01:00
|
|
|
cmp::Ordering,
|
|
|
|
time::{SystemTime, UNIX_EPOCH},
|
|
|
|
};
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-05-27 20:05:33 +00:00
|
|
|
pub use debug::slice_truncated as debug_slice_truncated;
|
|
|
|
pub use html::Escape as HtmlEscape;
|
|
|
|
pub use json::{deserialize_from_str, to_canonical_object};
|
2020-04-06 22:57:58 +02:00
|
|
|
use rand::prelude::*;
|
2022-10-05 18:36:12 +02:00
|
|
|
use ring::digest;
|
2024-05-27 20:05:33 +00:00
|
|
|
use ruma::OwnedUserId;
|
|
|
|
pub use sys::available_parallelism;
|
2024-05-09 15:59:08 -07:00
|
|
|
|
|
|
|
use crate::{Error, Result};
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn clamp<T: Ord>(val: T, min: T, max: T) -> T { cmp::min(cmp::max(val, min), max) }
|
2024-03-29 18:28:04 -07:00
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
#[must_use]
|
2024-05-04 09:45:37 -04:00
|
|
|
#[allow(clippy::as_conversions)]
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn millis_since_unix_epoch() -> u64 {
|
2024-03-25 17:05:11 -04:00
|
|
|
SystemTime::now()
|
|
|
|
.duration_since(UNIX_EPOCH)
|
|
|
|
.expect("time is valid")
|
|
|
|
.as_millis() as u64
|
2020-03-29 13:48:44 +02:00
|
|
|
}
|
2020-03-29 21:05:20 +02:00
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn increment(old: Option<&[u8]>) -> Vec<u8> {
|
2024-03-08 09:25:47 -05:00
|
|
|
let number = match old.map(TryInto::try_into) {
|
2020-06-09 15:13:17 +02:00
|
|
|
Some(Ok(bytes)) => {
|
|
|
|
let number = u64::from_be_bytes(bytes);
|
2020-03-30 13:46:18 +02:00
|
|
|
number + 1
|
|
|
|
},
|
2020-06-09 15:13:17 +02:00
|
|
|
_ => 1, // Start at one. since 0 should return the first event in the db
|
2020-03-30 13:46:18 +02:00
|
|
|
};
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-03-22 22:44:31 -04:00
|
|
|
number.to_be_bytes().to_vec()
|
2020-03-29 21:05:20 +02:00
|
|
|
}
|
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
#[must_use]
|
|
|
|
pub fn generate_keypair() -> Vec<u8> {
|
2021-06-08 18:10:00 +02:00
|
|
|
let mut value = random_string(8).as_bytes().to_vec();
|
|
|
|
value.push(0xFF);
|
|
|
|
value.extend_from_slice(
|
|
|
|
&ruma::signatures::Ed25519KeyPair::generate().expect("Ed25519KeyPair generation always works (?)"),
|
|
|
|
);
|
|
|
|
value
|
2020-04-19 14:14:47 +02:00
|
|
|
}
|
|
|
|
|
2020-05-03 17:25:31 +02:00
|
|
|
/// Parses the bytes into an u64.
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn u64_from_bytes(bytes: &[u8]) -> Result<u64, std::array::TryFromSliceError> {
|
2020-06-09 15:13:17 +02:00
|
|
|
let array: [u8; 8] = bytes.try_into()?;
|
|
|
|
Ok(u64::from_be_bytes(array))
|
2020-04-03 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2020-05-03 17:25:31 +02:00
|
|
|
/// Parses the bytes into a string.
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn string_from_bytes(bytes: &[u8]) -> Result<String, std::string::FromUtf8Error> {
|
2020-06-09 15:13:17 +02:00
|
|
|
String::from_utf8(bytes.to_vec())
|
2020-03-29 21:05:20 +02:00
|
|
|
}
|
2020-04-06 22:57:58 +02:00
|
|
|
|
2024-03-22 22:44:31 -04:00
|
|
|
/// Parses a `OwnedUserId` from bytes.
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn user_id_from_bytes(bytes: &[u8]) -> Result<OwnedUserId> {
|
2023-07-10 16:41:00 +02:00
|
|
|
OwnedUserId::try_from(
|
|
|
|
string_from_bytes(bytes).map_err(|_| Error::bad_database("Failed to parse string from bytes"))?,
|
|
|
|
)
|
|
|
|
.map_err(|_| Error::bad_database("Failed to parse user id from bytes"))
|
|
|
|
}
|
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn random_string(length: usize) -> String {
|
2024-03-25 17:05:11 -04:00
|
|
|
thread_rng()
|
|
|
|
.sample_iter(&rand::distributions::Alphanumeric)
|
|
|
|
.take(length)
|
|
|
|
.map(char::from)
|
|
|
|
.collect()
|
2020-04-06 22:57:58 +02:00
|
|
|
}
|
2020-04-14 22:25:44 +02:00
|
|
|
|
2022-10-05 18:36:12 +02:00
|
|
|
#[tracing::instrument(skip(keys))]
|
2024-05-09 15:59:08 -07:00
|
|
|
pub fn calculate_hash(keys: &[&[u8]]) -> Vec<u8> {
|
2022-10-05 18:36:12 +02:00
|
|
|
// We only hash the pdu's event ids, not the whole pdu
|
|
|
|
let bytes = keys.join(&0xFF);
|
|
|
|
let hash = digest::digest(&digest::SHA256, &bytes);
|
|
|
|
hash.as_ref().to_owned()
|
|
|
|
}
|
|
|
|
|
2024-05-09 15:59:08 -07:00
|
|
|
#[allow(clippy::impl_trait_in_params)]
|
|
|
|
pub fn common_elements(
|
2021-04-09 21:38:16 +02:00
|
|
|
mut iterators: impl Iterator<Item = impl Iterator<Item = Vec<u8>>>, check_order: impl Fn(&[u8], &[u8]) -> Ordering,
|
|
|
|
) -> Option<impl Iterator<Item = Vec<u8>>> {
|
2020-08-21 21:22:59 +02:00
|
|
|
let first_iterator = iterators.next()?;
|
2024-03-08 09:25:47 -05:00
|
|
|
let mut other_iterators = iterators.map(Iterator::peekable).collect::<Vec<_>>();
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2020-08-21 21:22:59 +02:00
|
|
|
Some(first_iterator.filter(move |target| {
|
2021-06-17 20:34:14 +02:00
|
|
|
other_iterators.iter_mut().all(|it| {
|
|
|
|
while let Some(element) = it.peek() {
|
|
|
|
match check_order(element, target) {
|
|
|
|
Ordering::Greater => return false, // We went too far
|
|
|
|
Ordering::Equal => return true, // Element is in both iters
|
|
|
|
Ordering::Less => {
|
|
|
|
// Keep searching
|
|
|
|
it.next();
|
2020-08-21 21:22:59 +02:00
|
|
|
},
|
|
|
|
}
|
2021-06-17 20:34:14 +02:00
|
|
|
}
|
|
|
|
false
|
|
|
|
})
|
2020-08-21 21:22:59 +02:00
|
|
|
}))
|
|
|
|
}
|
2020-11-18 08:36:12 -05:00
|
|
|
|
2024-05-25 21:24:17 +00:00
|
|
|
/// Boilerplate for wraps which are typed to never error.
|
|
|
|
///
|
|
|
|
/// * <https://doc.rust-lang.org/std/convert/enum.Infallible.html>
|
|
|
|
#[must_use]
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn unwrap_infallible<T>(result: Result<T, std::convert::Infallible>) -> T {
|
|
|
|
match result {
|
|
|
|
Ok(val) => val,
|
|
|
|
Err(err) => match err {},
|
|
|
|
}
|
|
|
|
}
|