miltr_common/modifications/
recipients.rs

1//! Add or delete recipients
2
3use std::borrow::Cow;
4
5use bytes::{BufMut, BytesMut};
6
7use crate::decoding::Parsable;
8use crate::encoding::Writable;
9use crate::{InvalidData, ProtocolError};
10use miltr_utils::ByteParsing;
11
12#[derive(Debug, Clone)]
13
14///Does not change To in Header
15pub struct AddRecipient {
16    recipient: BytesMut,
17}
18
19impl AddRecipient {
20    const CODE: u8 = b'+';
21
22    /// Add the specified recipient
23    #[must_use]
24    pub fn new(recipient: &[u8]) -> Self {
25        Self {
26            recipient: BytesMut::from_iter(recipient),
27        }
28    }
29
30    /// The recipient to add
31    #[must_use]
32    pub fn recipient(&self) -> Cow<str> {
33        String::from_utf8_lossy(&self.recipient)
34    }
35}
36
37impl Parsable for AddRecipient {
38    const CODE: u8 = Self::CODE;
39
40    fn parse(mut buffer: BytesMut) -> Result<Self, ProtocolError> {
41        let Some(recipient) = buffer.delimited(0) else {
42            return Err(InvalidData::new(
43                "Received add recipient package without null byte terminating it",
44                buffer,
45            )
46            .into());
47        };
48
49        Ok(Self { recipient })
50    }
51}
52
53impl Writable for AddRecipient {
54    ///buffer = recipients
55    fn write(&self, buffer: &mut BytesMut) {
56        buffer.extend_from_slice(&self.recipient);
57        buffer.put_u8(0);
58    }
59
60    fn len(&self) -> usize {
61        self.recipient.len() + 1
62    }
63
64    fn code(&self) -> u8 {
65        Self::CODE
66    }
67    fn is_empty(&self) -> bool {
68        self.len() == 0
69    }
70}
71
72#[derive(Debug, Clone)]
73/// Does not change To in Header
74pub struct DeleteRecipient {
75    recipient: BytesMut,
76}
77
78impl DeleteRecipient {
79    const CODE: u8 = b'-';
80
81    /// Delete the specified recipient
82    #[must_use]
83    pub fn new(recipient: &[u8]) -> Self {
84        Self {
85            recipient: BytesMut::from_iter(recipient),
86        }
87    }
88
89    /// The (exact) recipient to be deleted
90    #[must_use]
91    pub fn recipient(&self) -> Cow<str> {
92        String::from_utf8_lossy(&self.recipient)
93    }
94}
95
96impl Parsable for DeleteRecipient {
97    const CODE: u8 = Self::CODE;
98
99    fn parse(mut buffer: BytesMut) -> Result<Self, ProtocolError> {
100        let Some(recipient) = buffer.delimited(0) else {
101            return Err(InvalidData::new(
102                "Received delete recipient package without null byte terminating it",
103                buffer,
104            )
105            .into());
106        };
107
108        Ok(Self { recipient })
109    }
110}
111
112impl Writable for DeleteRecipient {
113    fn write(&self, buffer: &mut BytesMut) {
114        buffer.extend_from_slice(&self.recipient);
115        buffer.put_u8(0);
116    }
117
118    fn len(&self) -> usize {
119        self.recipient.len() + 1
120    }
121
122    fn code(&self) -> u8 {
123        Self::CODE
124    }
125
126    fn is_empty(&self) -> bool {
127        self.len() == 0
128    }
129}
130
131#[cfg(test)]
132mod test {
133    use super::*;
134
135    #[test]
136    fn test_add_recipient() {
137        let mut buffer = BytesMut::new();
138        let add_rcpt = AddRecipient {
139            recipient: BytesMut::from("alex@gmail"),
140        };
141        add_rcpt.write(&mut buffer);
142
143        assert_eq!(buffer.len(), add_rcpt.len());
144        assert_eq!(buffer, BytesMut::from("alex@gmail\0"));
145    }
146
147    #[test]
148    fn test_delete_recipient() {
149        let mut buffer = BytesMut::new();
150        let add_rcpt = AddRecipient {
151            recipient: BytesMut::from("alex@gmail"),
152        };
153        add_rcpt.write(&mut buffer);
154
155        assert_eq!(buffer.len(), add_rcpt.len());
156        assert_eq!(buffer, BytesMut::from("alex@gmail\0"));
157    }
158}