You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
2.6 KiB
125 lines
2.6 KiB
//! Building `Message<V>`s
|
|
use super::*;
|
|
use std::time::SystemTime;
|
|
|
|
/// Builder for the `Message<V>` type
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct MessageBuilder<V: ?Sized>
|
|
{
|
|
sign: bool,
|
|
encrypt: bool,
|
|
respond: Option<Uuid>,
|
|
|
|
_phantom: PhantomData<V>,
|
|
}
|
|
|
|
impl<V: ?Sized + MessageValue> Default for MessageBuilder<V>
|
|
{
|
|
#[inline]
|
|
fn default() -> Self
|
|
{
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
|
|
impl<V: ?Sized> MessageBuilder<V>
|
|
{
|
|
/// Create a new builder for a message with default settings
|
|
pub const fn new() -> Self
|
|
{
|
|
Self {
|
|
sign: false,
|
|
encrypt: false,
|
|
respond: None,
|
|
_phantom: PhantomData,
|
|
}
|
|
}
|
|
|
|
/// Specify if the message should be signed when serialized.
|
|
pub const fn sign(mut self, sign: bool) -> Self
|
|
{
|
|
self.sign = sign;
|
|
self
|
|
}
|
|
|
|
/// Specify if the message should be encrypted when serialized.
|
|
///
|
|
/// A key will be generated randomly for the message on creation.
|
|
pub const fn encrypt(mut self, encrypt: bool) -> Self
|
|
{
|
|
self.encrypt = encrypt;
|
|
self
|
|
}
|
|
|
|
/// Specify a message ID that this message should respond to.
|
|
pub const fn respond(mut self, to: Uuid) -> Self
|
|
{
|
|
self.respond = Some(to);
|
|
self
|
|
}
|
|
|
|
/// Create a new builder with the capabilities of a sender
|
|
#[cfg(nightly)]
|
|
pub const fn for_sender<S: ?Sized + MessageSender>() -> Self
|
|
{
|
|
Self::new()
|
|
.sign(S::CAP_SIGN)
|
|
.encrypt(S::CAP_ENCRYPT)
|
|
}
|
|
|
|
/// Create a new builder with the capabilities of a sender
|
|
#[cfg(not(nightly))]
|
|
pub fn for_sender<S: ?Sized + MessageSender>() -> Self
|
|
{
|
|
Self::new()
|
|
.sign(S::CAP_SIGN)
|
|
.encrypt(S::CAP_ENCRYPT)
|
|
}
|
|
}
|
|
|
|
impl<V: ?Sized + MessageValue> MessageBuilder<V>
|
|
{
|
|
|
|
/// Create a message from this builder with this value.
|
|
pub fn create(self, value: V) -> eyre::Result<Message<V>>
|
|
{
|
|
let key = if self.encrypt {
|
|
Some(aes::AesKey::generate().wrap_err(eyre!("Failed to generate session key"))?)
|
|
} else {
|
|
None
|
|
};
|
|
let header = SerHeader::new(self.respond);
|
|
|
|
Ok(Message {
|
|
header,
|
|
key,
|
|
sign: self.sign,
|
|
value,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Get the current unix timestamp.
|
|
pub(super) fn timestamp_now() -> u64
|
|
{
|
|
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
|
|
Ok(n) => n.as_secs(),
|
|
Err(_) => panic!("Timestamp for now returned before unix epoch."),
|
|
}
|
|
}
|
|
|
|
impl SerHeader
|
|
{
|
|
/// Create a new header with optional response ID.
|
|
#[inline] pub fn new(responds: Option<Uuid>) -> Self
|
|
{
|
|
Self {
|
|
id: Uuid::new_v4(),
|
|
idemp: Uuid::new_v4(),
|
|
timestamp: timestamp_now(),
|
|
responds_to: responds,
|
|
}
|
|
}
|
|
}
|