Types Creation
This commit is contained in:
parent
94f2280570
commit
8337fa3d8f
22 changed files with 1141 additions and 202 deletions
|
|
@ -7,13 +7,12 @@ edition = "2024"
|
|||
mtp-type-map = { path = "../type-map" }
|
||||
mtp-common = { path = "../common" }
|
||||
mtp-crypto = { path = "../crypto", optional = true }
|
||||
registry = { path = "../registry", optional = true }
|
||||
base64 = "*"
|
||||
byteorder = "*"
|
||||
rand = { version = "*", features = ["std", "std_rng"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
# Enables the Registry module and versioned codec wrapper
|
||||
registry = []
|
||||
# Enables EncryptedContainer support via mtp-crypto
|
||||
registry = ["dep:registry"]
|
||||
crypto = ["dep:mtp-crypto"]
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
// Communication types used in the MTP protocol.
|
||||
// The numeric values are part of the on‑wire 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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!()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue