openmls/messages/
codec.rs

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