[Updt] Mtp 0.3.0

This commit is contained in:
Alex 2026-08-20 17:05:43 +02:00
commit ad8555bc6e
Signed by: alex
SSH key fingerprint: SHA256:D1+Ub8o0v4K5y1JNivW8IxEOelqLSvPmUzBbDIoZkRQ
45 changed files with 2019 additions and 1441 deletions

View file

@ -6,7 +6,10 @@ pub fn generate_keyring() -> Keyring {
}
pub fn keyring_to_base64(keyring: &Keyring) -> String {
STANDARD.encode(keyring.to_bytes())
let bytes = keyring
.try_to_bytes()
.expect("keyring fields must fit the wire format");
STANDARD.encode(bytes)
}
pub fn keyring_from_base64(s: &str) -> Option<Keyring> {
@ -15,7 +18,10 @@ pub fn keyring_from_base64(s: &str) -> Option<Keyring> {
}
pub fn public_key_bundle_to_base64(bundle: &PublicKeyBundle) -> String {
STANDARD.encode(bundle.as_bytes())
let bytes = bundle
.try_as_bytes()
.expect("public key bundle fields must fit the wire format");
STANDARD.encode(bytes)
}
pub fn public_key_bundle_from_base64(s: &str) -> Option<PublicKeyBundle> {

View file

@ -1,28 +1,42 @@
use mtp::codec::{CommunicationValue, DataValue};
use mtp::type_map::DataTypeId;
/*
* Keep legacy control-plane handlers source-compatible while they migrate to
* MTP's explicit optional routing fields. Relay handlers must use sender() and
* receiver() directly so an absent outer sender cannot become an identity.
*/
pub trait CommunicationValueCompat {
fn get_id(&self) -> u32;
fn get_sender(&self) -> u64;
fn get_receiver(&self) -> u64;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MtpFieldError {
MissingId,
MissingSender,
MissingReceiver,
}
impl CommunicationValueCompat for CommunicationValue {
fn get_id(&self) -> u32 {
self.id().unwrap_or_default()
impl std::fmt::Display for MtpFieldError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::MissingId => "missing message id",
Self::MissingSender => "missing sender",
Self::MissingReceiver => "missing receiver",
})
}
}
impl std::error::Error for MtpFieldError {}
pub trait RequiredCommunicationFields {
fn require_id(&self) -> Result<u32, MtpFieldError>;
fn require_sender(&self) -> Result<u64, MtpFieldError>;
fn require_receiver(&self) -> Result<u64, MtpFieldError>;
}
impl RequiredCommunicationFields for CommunicationValue {
fn require_id(&self) -> Result<u32, MtpFieldError> {
self.id().ok_or(MtpFieldError::MissingId)
}
fn get_sender(&self) -> u64 {
self.sender().unwrap_or_default()
fn require_sender(&self) -> Result<u64, MtpFieldError> {
self.sender().ok_or(MtpFieldError::MissingSender)
}
fn get_receiver(&self) -> u64 {
self.receiver().unwrap_or_default()
fn require_receiver(&self) -> Result<u64, MtpFieldError> {
self.receiver().ok_or(MtpFieldError::MissingReceiver)
}
}
@ -65,3 +79,33 @@ impl<'a> OptionalDataValueExt<'a> for Option<&'a DataValue> {
self.and_then(DataValue::as_container)
}
}
#[cfg(test)]
mod tests {
use super::{MtpFieldError, RequiredCommunicationFields};
use mtp::codec::{CommunicationType, CommunicationValue};
#[test]
fn missing_routing_fields_are_reported_instead_of_defaulted() {
let message = CommunicationValue::new(CommunicationType::Success).without_id();
assert_eq!(message.require_id(), Err(MtpFieldError::MissingId));
assert_eq!(message.require_sender(), Err(MtpFieldError::MissingSender));
assert_eq!(
message.require_receiver(),
Err(MtpFieldError::MissingReceiver)
);
}
#[test]
fn present_routing_fields_are_returned_unchanged() {
let message = CommunicationValue::new(CommunicationType::Success)
.with_id(7)
.with_sender(8)
.with_receiver(9);
assert_eq!(message.require_id(), Ok(7));
assert_eq!(message.require_sender(), Ok(8));
assert_eq!(message.require_receiver(), Ok(9));
}
}