Types Creation

This commit is contained in:
Alex Emmet 2026-06-21 22:57:50 +02:00
commit 8337fa3d8f
22 changed files with 1141 additions and 202 deletions

View file

@ -1,25 +0,0 @@
// Communication types used in the MTP protocol.
// The numeric values are part of the onwire format.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum CommunicationType {
ping = 0x0001,
message_send = 0x0002,
update = 0x0003,
}
impl CommunicationType {
pub fn as_number(self) -> u16 {
self as u16
}
pub fn from_number(n: u16) -> Self {
match n {
0x0001 => CommunicationType::ping,
0x0002 => CommunicationType::message_send,
0x0003 => CommunicationType::update,
_ => CommunicationType::ping,
}
}
}

View file

@ -4,12 +4,12 @@ use std::io::{Cursor, Read};
use crate::data_value::DataValue;
use crate::rand_u32;
use mtp_type_map::{CommTypeId, DataTypeId};
use mtp_type_map::{CommunicationTypeId, DataTypeId};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CommunicationValue {
id: u32,
comm_type: CommTypeId,
comm_type: CommunicationTypeId,
sender: u64,
receiver: u64,
data: BTreeMap<DataTypeId, DataValue>,
@ -17,7 +17,7 @@ pub struct CommunicationValue {
#[allow(dead_code)]
impl CommunicationValue {
pub fn new(comm_type: CommTypeId) -> Self {
pub fn new(comm_type: CommunicationTypeId) -> Self {
Self {
id: rand_u32(),
comm_type,
@ -54,11 +54,11 @@ impl CommunicationValue {
self.receiver
}
pub fn get_type(&self) -> CommTypeId {
pub fn get_type(&self) -> CommunicationTypeId {
self.comm_type
}
pub fn is_type(&self, p0: CommTypeId) -> bool {
pub fn is_type(&self, p0: CommunicationTypeId) -> bool {
self.comm_type == p0
}
@ -149,7 +149,7 @@ impl CommunicationValue {
let frame_end = 4 + total_len;
let comm_type_num = cursor.read_u16::<BigEndian>().ok()?;
let comm_type = CommTypeId(comm_type_num);
let comm_type = CommunicationTypeId(comm_type_num);
let flags = cursor.read_u8().ok()?;
let has_sender = (flags & 0b0000_0001) != 0;
@ -201,7 +201,7 @@ impl CommunicationValue {
mod tests {
use super::*;
use crate::data_value::DataValue;
use mtp_type_map::{CommTypeId, DataTypeId};
use mtp_type_map::{CommunicationTypeId, DataTypeId};
fn roundtrip(cv: CommunicationValue) -> CommunicationValue {
let bytes = cv.to_bytes();
@ -213,7 +213,7 @@ mod tests {
#[test]
fn test_flags_and_order_without_optional() {
let cv = CommunicationValue::new(CommTypeId(1)).with_id(0);
let cv = CommunicationValue::new(CommunicationTypeId(1)).with_id(0);
let bytes = cv.to_bytes();
// [u32 len][u16 type][flags]...
@ -231,7 +231,7 @@ mod tests {
#[test]
fn test_flags_and_order_with_all_optional() {
let cv = CommunicationValue::new(CommTypeId(2))
let cv = CommunicationValue::new(CommunicationTypeId(2))
.with_id(0xAABBCCDD)
.with_sender(0x0000_1122_3344_5566)
.with_receiver(0x0000_6677_8899_AABB);
@ -262,7 +262,7 @@ mod tests {
#[test]
fn test_roundtrip_complex() {
let cv = CommunicationValue::new(CommTypeId(3))
let cv = CommunicationValue::new(CommunicationTypeId(3))
.with_id(1234)
.with_sender(111)
.with_receiver(222)
@ -279,7 +279,7 @@ mod tests {
assert_eq!(decoded.get_id(), 1234);
assert_eq!(decoded.get_sender(), 111);
assert_eq!(decoded.get_receiver(), 222);
assert_eq!(decoded.get_type(), CommTypeId(3));
assert_eq!(decoded.get_type(), CommunicationTypeId(3));
assert_eq!(
decoded.get_data(DataTypeId(1)),
&DataValue::Str("alice".to_string())

View file

@ -204,9 +204,11 @@ impl DataValue {
}
}
/// Decrypt an `EncryptedContainer` in-place, replacing it with the
/// deserialized `Container`. Returns `None` if decryption or
/// deserialization fails.
/*
* Decrypt an `EncryptedContainer` in-place, replacing it with the
* deserialized `Container`. Returns `None` if decryption or
* deserialization fails.
*/
#[cfg(feature = "crypto")]
pub fn decrypt_into_container(
&mut self,
@ -225,8 +227,10 @@ impl DataValue {
}
}
/// Encrypt a `Container` into an `EncryptedContainer` in-place.
/// Returns `None` if the value is not a `Container` or encryption fails.
/*
* Encrypt a `Container` into an `EncryptedContainer` in-place.
* Returns `None` if the value is not a `Container` or encryption fails.
*/
#[cfg(feature = "crypto")]
pub fn encrypt_container(
&mut self,

View file

@ -1,4 +1,3 @@
pub mod communication_types;
pub mod communication_value;
pub mod data_value;
pub mod util;
@ -8,17 +7,17 @@ pub use data_value::{DataKind, DataValue};
pub use util::rand_u32;
pub use mtp_type_map::{CommTypeId, DataTypeId, TypeMap, Version};
pub use mtp_type_map::{
CommunicationType, CommunicationTypeId, DataType, DataTypeId, TypeMap, Version,
};
use mtp_common::CodecError;
pub fn encode(_value: &DataValue, _typemap: &TypeMap) -> Result<Vec<u8>, CodecError> {
// write header using typemap.data_id(), serialize value
todo!()
}
pub fn decode(_bytes: &[u8], _typemap: &TypeMap) -> Result<DataValue, CodecError> {
// read header, look up type names from typemap, build DataValue
todo!()
}

View file

@ -1,40 +1,12 @@
pub use registry::Registry;
use crate::{CodecError, DataValue, decode, encode};
use std::collections::BTreeMap;
use type_map::{TypeMap, Version};
#[derive(Clone, Debug)]
pub struct Registry {
versions: BTreeMap<Version, TypeMap>,
}
impl Registry {
pub fn new() -> Self {
Self {
versions: BTreeMap::new(),
}
}
pub fn register(&mut self, typemap: TypeMap) {
self.versions.insert(typemap.version.clone(), typemap);
}
pub fn get(&self, version: Version) -> Option<&TypeMap> {
self.versions.get(&version)
}
pub fn negotiate(&self, client_versions: &[Version]) -> Option<Version> {
client_versions
.iter()
.filter(|v| self.versions.contains_key(v))
.max()
.cloned()
}
pub fn latest(&self) -> Option<&TypeMap> {
self.versions.last_key_value().map(|(_, v)| v)
}
}
use mtp_type_map::Version;
/*
* A version-aware codec that uses a multi-version registry to resolve
* the correct TypeMap for encoding and decoding operations.
*/
#[derive(Clone, Debug)]
pub struct VersionedCodec {
registry: Registry,
@ -48,7 +20,7 @@ impl VersionedCodec {
pub fn encode(&self, value: &DataValue, version: Version) -> Result<Vec<u8>, CodecError> {
let typemap = self
.registry
.get(version)
.get(&version)
.ok_or(CodecError::UnknownVersion)?;
encode(value, typemap)
}
@ -56,7 +28,7 @@ impl VersionedCodec {
pub fn decode(&self, bytes: &[u8], version: Version) -> Result<DataValue, CodecError> {
let typemap = self
.registry
.get(version)
.get(&version)
.ok_or(CodecError::UnknownVersion)?;
decode(bytes, typemap)
}
@ -64,4 +36,8 @@ impl VersionedCodec {
pub fn negotiate(&self, client_versions: &[Version]) -> Option<Version> {
self.registry.negotiate(client_versions)
}
pub fn registry(&self) -> &Registry {
&self.registry
}
}