openmls/messages/
codec.rs1use tls_codec::{Deserialize, DeserializeBytes, Serialize, Size};
6
7use super::{
8 proposals::{
9 ExternalInitProposal, GroupContextExtensionProposal, PreSharedKeyProposal, Proposal,
10 ProposalType, ReInitProposal, RemoveProposal,
11 },
12 proposals_in::{AddProposalIn, ProposalIn, UpdateProposalIn},
13 CustomProposal,
14};
15
16#[cfg(feature = "extensions-draft-08")]
17use super::proposals::AppEphemeralProposal;
18
19impl Size for Proposal {
20 fn tls_serialized_len(&self) -> usize {
21 self.proposal_type().tls_serialized_len()
22 + match self {
23 Proposal::Add(p) => p.tls_serialized_len(),
24 Proposal::Update(p) => p.tls_serialized_len(),
25 Proposal::Remove(p) => p.tls_serialized_len(),
26 Proposal::PreSharedKey(p) => p.tls_serialized_len(),
27 Proposal::ReInit(p) => p.tls_serialized_len(),
28 Proposal::ExternalInit(p) => p.tls_serialized_len(),
29 Proposal::GroupContextExtensions(p) => p.tls_serialized_len(),
30 Proposal::SelfRemove => 0,
31 #[cfg(feature = "extensions-draft-08")]
32 Proposal::AppEphemeral(p) => p.tls_serialized_len(),
33 Proposal::Custom(p) => p.payload().tls_serialized_len(),
34 }
35 }
36}
37
38impl Serialize for Proposal {
39 fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
40 let written = self.proposal_type().tls_serialize(writer)?;
41 match self {
42 Proposal::Add(p) => p.tls_serialize(writer),
43 Proposal::Update(p) => p.tls_serialize(writer),
44 Proposal::Remove(p) => p.tls_serialize(writer),
45 Proposal::PreSharedKey(p) => p.tls_serialize(writer),
46 Proposal::ReInit(p) => p.tls_serialize(writer),
47 Proposal::ExternalInit(p) => p.tls_serialize(writer),
48 Proposal::GroupContextExtensions(p) => p.tls_serialize(writer),
49 Proposal::SelfRemove => Ok(0),
50 #[cfg(feature = "extensions-draft-08")]
51 Proposal::AppEphemeral(p) => p.tls_serialize(writer),
52 Proposal::Custom(p) => p.payload().tls_serialize(writer),
53 }
54 .map(|l| written + l)
55 }
56}
57
58impl Size for &ProposalIn {
59 fn tls_serialized_len(&self) -> usize {
60 self.proposal_type().tls_serialized_len()
61 + match self {
62 ProposalIn::Add(p) => p.tls_serialized_len(),
63 ProposalIn::Update(p) => p.tls_serialized_len(),
64 ProposalIn::Remove(p) => p.tls_serialized_len(),
65 ProposalIn::PreSharedKey(p) => p.tls_serialized_len(),
66 ProposalIn::ReInit(p) => p.tls_serialized_len(),
67 ProposalIn::ExternalInit(p) => p.tls_serialized_len(),
68 ProposalIn::GroupContextExtensions(p) => p.tls_serialized_len(),
69 ProposalIn::SelfRemove => 0,
70 #[cfg(feature = "extensions-draft-08")]
71 ProposalIn::AppEphemeral(p) => p.tls_serialized_len(),
72 ProposalIn::Custom(p) => p.payload().tls_serialized_len(),
73 }
74 }
75}
76
77impl Size for ProposalIn {
78 fn tls_serialized_len(&self) -> usize {
79 (&self).tls_serialized_len()
80 }
81}
82
83impl Serialize for &ProposalIn {
84 fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
85 let written = self.proposal_type().tls_serialize(writer)?;
86 match self {
87 ProposalIn::Add(p) => p.tls_serialize(writer),
88 ProposalIn::Update(p) => p.tls_serialize(writer),
89 ProposalIn::Remove(p) => p.tls_serialize(writer),
90 ProposalIn::PreSharedKey(p) => p.tls_serialize(writer),
91 ProposalIn::ReInit(p) => p.tls_serialize(writer),
92 ProposalIn::ExternalInit(p) => p.tls_serialize(writer),
93 ProposalIn::GroupContextExtensions(p) => p.tls_serialize(writer),
94 ProposalIn::SelfRemove => Ok(0),
95 #[cfg(feature = "extensions-draft-08")]
96 ProposalIn::AppEphemeral(p) => p.tls_serialize(writer),
97 ProposalIn::Custom(p) => p.payload().tls_serialize(writer),
98 }
99 .map(|l| written + l)
100 }
101}
102
103impl Serialize for ProposalIn {
104 fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
105 (&self).tls_serialize(writer)
106 }
107}
108
109impl Deserialize for ProposalIn {
110 fn tls_deserialize<R: std::io::Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
111 where
112 Self: Sized,
113 {
114 let proposal_type = ProposalType::tls_deserialize(bytes)?;
115 let proposal = match proposal_type {
116 ProposalType::Add => ProposalIn::Add(Box::new(AddProposalIn::tls_deserialize(bytes)?)),
117 ProposalType::Update => {
118 ProposalIn::Update(Box::new(UpdateProposalIn::tls_deserialize(bytes)?))
119 }
120 ProposalType::Remove => {
121 ProposalIn::Remove(Box::new(RemoveProposal::tls_deserialize(bytes)?))
122 }
123 ProposalType::PreSharedKey => {
124 ProposalIn::PreSharedKey(Box::new(PreSharedKeyProposal::tls_deserialize(bytes)?))
125 }
126 ProposalType::Reinit => {
127 ProposalIn::ReInit(Box::new(ReInitProposal::tls_deserialize(bytes)?))
128 }
129 ProposalType::ExternalInit => {
130 ProposalIn::ExternalInit(Box::new(ExternalInitProposal::tls_deserialize(bytes)?))
131 }
132 ProposalType::GroupContextExtensions => ProposalIn::GroupContextExtensions(Box::new(
133 GroupContextExtensionProposal::tls_deserialize(bytes)?,
134 )),
135 ProposalType::SelfRemove => ProposalIn::SelfRemove,
136 #[cfg(feature = "extensions-draft-08")]
137 ProposalType::AppEphemeral => {
138 ProposalIn::AppEphemeral(Box::new(AppEphemeralProposal::tls_deserialize(bytes)?))
139 }
140 ProposalType::Custom(_) => {
141 let payload = Vec::<u8>::tls_deserialize(bytes)?;
142 let custom_proposal = CustomProposal::new(proposal_type.into(), payload);
143 ProposalIn::Custom(Box::new(custom_proposal))
144 }
145 };
146 Ok(proposal)
147 }
148}
149
150impl DeserializeBytes for ProposalIn {
151 fn tls_deserialize_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), tls_codec::Error>
152 where
153 Self: Sized,
154 {
155 let mut bytes_ref = bytes;
156 let proposal = ProposalIn::tls_deserialize(&mut bytes_ref)?;
157 let remainder = &bytes[proposal.tls_serialized_len()..];
158 Ok((proposal, remainder))
159 }
160}