litep2p/codec/
identity.rs

1// Copyright 2023 litep2p developers
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21//! Identity codec that reads/writes `N` bytes from/to source/sink.
22
23use crate::error::Error;
24
25use bytes::{BufMut, Bytes, BytesMut};
26use tokio_util::codec::{Decoder, Encoder};
27
28/// Identity codec.
29pub struct Identity {
30    payload_len: usize,
31}
32
33impl Identity {
34    /// Create new [`Identity`] codec.
35    pub fn new(payload_len: usize) -> Self {
36        assert!(payload_len != 0);
37
38        Self { payload_len }
39    }
40
41    /// Encode `payload` using identity codec.
42    pub fn encode<T: Into<Bytes>>(payload: T) -> crate::Result<Vec<u8>> {
43        let payload: Bytes = payload.into();
44        Ok(payload.into())
45    }
46}
47
48impl Decoder for Identity {
49    type Item = BytesMut;
50    type Error = Error;
51
52    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
53        if src.is_empty() {
54            return Ok(None);
55        }
56
57        Ok(Some(src.split_to(self.payload_len)))
58    }
59}
60
61impl Encoder<Bytes> for Identity {
62    type Error = Error;
63
64    fn encode(&mut self, item: Bytes, dst: &mut bytes::BytesMut) -> Result<(), Self::Error> {
65        if item.len() > self.payload_len || item.is_empty() {
66            return Err(Error::InvalidData);
67        }
68
69        dst.put_slice(item.as_ref());
70        Ok(())
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn encoding_works() {
80        let mut codec = Identity::new(48);
81        let mut out_buf = BytesMut::with_capacity(32);
82        let bytes = Bytes::from(vec![0u8; 48]);
83
84        assert!(codec.encode(bytes.clone(), &mut out_buf).is_ok());
85        assert_eq!(out_buf.freeze(), bytes);
86    }
87
88    #[test]
89    fn decoding_works() {
90        let mut codec = Identity::new(64);
91        let bytes = vec![3u8; 64];
92        let copy = bytes.clone();
93        let mut bytes = BytesMut::from(&bytes[..]);
94
95        let decoded = codec.decode(&mut bytes).unwrap().unwrap();
96        assert_eq!(decoded, copy);
97    }
98
99    #[test]
100    fn empty_encode() {
101        let mut codec = Identity::new(32);
102        let mut out_buf = BytesMut::with_capacity(32);
103        assert!(codec.encode(Bytes::new(), &mut out_buf).is_err());
104    }
105
106    #[test]
107    fn decode_encode() {
108        let mut codec = Identity::new(32);
109        assert!(codec.decode(&mut BytesMut::new()).unwrap().is_none());
110    }
111
112    #[test]
113    fn direct_encoding_works() {
114        assert_eq!(
115            Identity::encode(vec![1, 3, 3, 7]).unwrap(),
116            vec![1, 3, 3, 7]
117        );
118    }
119
120    #[test]
121    #[should_panic]
122    #[cfg(debug_assertions)]
123    fn empty_identity_codec() {
124        let _codec = Identity::new(0usize);
125    }
126}