1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use super::{BodyBytes, BodyBytesMut};

use bytes::{Bytes, BytesMut};


/// A trait that allows efficient allocation if encryption is
/// used or not.
pub trait PacketBytes: std::fmt::Debug {
	/// Creates a new Bytes instance.
	///
	/// It must always have header len available and initialized
	fn new(header_len: usize) -> Self;

	/// Returns the header Bytes.
	fn header(&self) -> Bytes<'_>;

	/// Returns the header mutably.
	fn header_mut(&mut self) -> BytesMut<'_>;

	/// Returns the full header mutably.
	/// 
	/// ## Note
	/// This should only be used to fill the buffer from a reader, in any other
	/// case you should use `header_mut`.
	fn full_header_mut(&mut self) -> BytesMut<'_>;

	/// Returns the body.
	fn body(&self) -> BodyBytes<'_>;

	/// Returns the body mutably.
	fn body_mut(&mut self) -> BodyBytesMut<'_>;

	/// Returns the full body mutably.
	/// 
	/// ## Note
	/// This should only be used to fill the buffer from a reader, in any other
	/// case you should use `body_mut`.
	fn full_body_mut(&mut self) -> BytesMut<'_>;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PlainBytes {
	bytes: Vec<u8>,
	header_len: usize
}

impl PacketBytes for PlainBytes {
	fn new(header_len: usize) -> Self {
		Self {
			bytes: vec![0; header_len],
			header_len
		}
	}

	fn header(&self) -> Bytes<'_> {
		self.bytes[..self.header_len].into()
	}

	fn header_mut(&mut self) -> BytesMut<'_> {
		(&mut self.bytes[..self.header_len]).into()
	}

	fn full_header_mut(&mut self) -> BytesMut<'_> {
		self.header_mut()
	}

	fn body(&self) -> BodyBytes<'_> {
		BodyBytes::new(&self.bytes[self.header_len..])
	}

	fn body_mut(&mut self) -> BodyBytesMut<'_> {
		BodyBytesMut::new(self.header_len, &mut self.bytes)
	}

	fn full_body_mut(&mut self) -> BytesMut<'_> {
		(&mut self.bytes[self.header_len..]).into()
	}
}

impl PlainBytes {
	#[cfg_attr(not(feature = "connection"), allow(dead_code))]
	pub(crate) fn as_slice(&self) -> &[u8] {
		&*self.bytes
	}
}


#[cfg(test)]
pub(super) mod tests {
	use super::*;
	use bytes::{BytesOwned, BytesRead, BytesWrite};

	pub fn test_gen_msg<B: PacketBytes>() {
		let header = [10u8; 30];
		let mut bytes = B::new(header.len());
		bytes.header_mut().write(&header);
		assert_eq!(bytes.body().len(), 0);

		{
			let mut body = bytes.body_mut();

			// now i can't use bytes
			// but body

			body.write_u32(10u32);
			body.write_u32(20u32);
		}

		// assert_eq!(bytes.as_slice().len(), 16 + 30 + 16 + 4 + 4);

		assert_eq!(bytes.header().as_slice(), header);

		let mut body = BytesOwned::new();
		body.write_u32(10);
		body.write_u32(20);
		assert_eq!(bytes.body().as_slice(), body.as_slice());
		assert_eq!(bytes.body().len(), body.len());
	}

	#[test]
	fn plain_bytes() {
		test_gen_msg::<PlainBytes>();
	}
}