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.
rsh/src/message/builder.rs

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,
}
}
}