-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add codecs support and one new codec (#352)
- Loading branch information
Showing
9 changed files
with
1,387 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use std::collections::HashMap; | ||
|
||
use prost::Message; | ||
use xmtp_proto::xmtp::mls::message_contents::{ | ||
ContentTypeId, EncodedContent, GroupMembershipChange, | ||
}; | ||
|
||
use super::{CodecError, ContentCodec}; | ||
|
||
pub struct GroupMembershipChangeCodec {} | ||
|
||
impl GroupMembershipChangeCodec { | ||
const AUTHORITY_ID: &'static str = "xmtp.org"; | ||
const TYPE_ID: &'static str = "group_membership_change"; | ||
} | ||
|
||
impl ContentCodec<GroupMembershipChange> for GroupMembershipChangeCodec { | ||
fn content_type() -> ContentTypeId { | ||
ContentTypeId { | ||
authority_id: GroupMembershipChangeCodec::AUTHORITY_ID.to_string(), | ||
type_id: GroupMembershipChangeCodec::TYPE_ID.to_string(), | ||
version_major: 1, | ||
version_minor: 0, | ||
} | ||
} | ||
|
||
fn encode(data: GroupMembershipChange) -> Result<EncodedContent, CodecError> { | ||
let mut buf = Vec::new(); | ||
data.encode(&mut buf) | ||
.map_err(|e| CodecError::Encode(e.to_string()))?; | ||
|
||
Ok(EncodedContent { | ||
r#type: Some(GroupMembershipChangeCodec::content_type()), | ||
parameters: HashMap::new(), | ||
fallback: None, | ||
compression: None, | ||
content: buf, | ||
}) | ||
} | ||
|
||
fn decode(content: EncodedContent) -> Result<GroupMembershipChange, CodecError> { | ||
let decoded = GroupMembershipChange::decode(content.content.as_slice()) | ||
.map_err(|e| CodecError::Decode(e.to_string()))?; | ||
|
||
Ok(decoded) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use xmtp_proto::xmtp::mls::message_contents::Member; | ||
|
||
use crate::utils::test::{rand_string, rand_vec}; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
fn test_encode_decode() { | ||
let new_member = Member { | ||
installation_ids: vec![rand_vec()], | ||
wallet_address: rand_string(), | ||
}; | ||
let data = GroupMembershipChange { | ||
members_added: vec![new_member.clone()], | ||
members_removed: vec![], | ||
installations_added: vec![], | ||
installations_removed: vec![], | ||
}; | ||
|
||
let encoded = GroupMembershipChangeCodec::encode(data).unwrap(); | ||
assert_eq!( | ||
encoded.clone().r#type.unwrap().type_id, | ||
"group_membership_change" | ||
); | ||
assert!(encoded.content.len() > 0); | ||
|
||
let decoded = GroupMembershipChangeCodec::decode(encoded).unwrap(); | ||
assert_eq!(decoded.members_added[0], new_member); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
pub mod membership_change; | ||
pub mod text; | ||
|
||
use thiserror::Error; | ||
use xmtp_proto::xmtp::mls::message_contents::{ContentTypeId, EncodedContent}; | ||
|
||
#[derive(Debug, Error)] | ||
pub enum CodecError { | ||
#[error("encode error {0}")] | ||
Encode(String), | ||
#[error("decode error {0}")] | ||
Decode(String), | ||
} | ||
|
||
pub trait ContentCodec<T> { | ||
fn content_type() -> ContentTypeId; | ||
fn encode(content: T) -> Result<EncodedContent, CodecError>; | ||
fn decode(content: EncodedContent) -> Result<T, CodecError>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
use std::collections::HashMap; | ||
|
||
use xmtp_proto::xmtp::mls::message_contents::{ContentTypeId, EncodedContent}; | ||
|
||
use super::{CodecError, ContentCodec}; | ||
|
||
pub struct TextCodec {} | ||
|
||
impl TextCodec { | ||
const AUTHORITY_ID: &'static str = "xmtp.org"; | ||
const TYPE_ID: &'static str = "text"; | ||
const ENCODING_KEY: &'static str = "encoding"; | ||
const ENCODING_UTF8: &'static str = "UTF-8"; | ||
} | ||
|
||
impl ContentCodec<String> for TextCodec { | ||
fn content_type() -> ContentTypeId { | ||
ContentTypeId { | ||
authority_id: TextCodec::AUTHORITY_ID.to_string(), | ||
type_id: TextCodec::TYPE_ID.to_string(), | ||
version_major: 1, | ||
version_minor: 0, | ||
} | ||
} | ||
|
||
fn encode(text: String) -> Result<EncodedContent, CodecError> { | ||
Ok(EncodedContent { | ||
r#type: Some(TextCodec::content_type()), | ||
parameters: HashMap::from([( | ||
TextCodec::ENCODING_KEY.to_string(), | ||
TextCodec::ENCODING_UTF8.to_string(), | ||
)]), | ||
fallback: None, | ||
compression: None, | ||
content: text.into_bytes(), | ||
}) | ||
} | ||
|
||
fn decode(content: EncodedContent) -> Result<String, CodecError> { | ||
let encoding = content | ||
.parameters | ||
.get(TextCodec::ENCODING_KEY) | ||
.map_or(TextCodec::ENCODING_UTF8, String::as_str); | ||
if encoding != TextCodec::ENCODING_UTF8 { | ||
return Err(CodecError::Decode(format!( | ||
"Unsupported text encoding {}", | ||
encoding | ||
))); | ||
} | ||
let text = std::str::from_utf8(&content.content) | ||
.map_err(|utf8_err| CodecError::Decode(utf8_err.to_string()))?; | ||
Ok(text.to_string()) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::codecs::{text::TextCodec, ContentCodec}; | ||
|
||
#[test] | ||
fn can_encode_and_decode_text() { | ||
let text = "Hello, world!"; | ||
let encoded_content = | ||
TextCodec::encode(text.to_string()).expect("Should encode successfully"); | ||
let decoded_content = | ||
TextCodec::decode(encoded_content).expect("Should decode successfully"); | ||
assert!(decoded_content == text); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.