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