1use crate::{Decode, Encode, EncodedSize, Result, VarInt};
2
3#[derive(Debug, Clone, Default, PartialEq)]
18pub struct Slot {
19 pub item_count: i32,
21 pub item_id: Option<i32>,
23 pub component_data: Vec<u8>,
27}
28
29impl Slot {
30 pub fn empty() -> Self {
32 Self {
33 item_count: 0,
34 item_id: None,
35 component_data: Vec::new(),
36 }
37 }
38
39 pub fn new(item_id: i32, count: i32) -> Self {
41 Self {
42 item_count: count,
43 item_id: Some(item_id),
44 component_data: Vec::new(),
45 }
46 }
47
48 pub fn is_empty(&self) -> bool {
50 self.item_count == 0
51 }
52}
53
54impl Encode for Slot {
60 fn encode(&self, buf: &mut Vec<u8>) -> Result<()> {
62 VarInt(self.item_count).encode(buf)?;
63 if self.item_count > 0 {
64 if let Some(item_id) = self.item_id {
65 VarInt(item_id).encode(buf)?;
66 }
67 if self.component_data.is_empty() {
68 VarInt(0).encode(buf)?; VarInt(0).encode(buf)?; } else {
72 buf.extend_from_slice(&self.component_data);
73 }
74 }
75 Ok(())
76 }
77}
78
79impl Decode for Slot {
87 fn decode(buf: &mut &[u8]) -> Result<Self> {
89 let item_count = VarInt::decode(buf)?.0;
90 if item_count <= 0 {
91 return Ok(Self::empty());
92 }
93
94 let item_id = VarInt::decode(buf)?.0;
95
96 let num_add = VarInt::decode(buf)?.0;
98 let num_remove = VarInt::decode(buf)?.0;
99
100 if num_add == 0 && num_remove == 0 {
101 return Ok(Self {
103 item_count,
104 item_id: Some(item_id),
105 component_data: Vec::new(),
106 });
107 }
108
109 let mut component_data = Vec::new();
111 VarInt(num_add).encode(&mut component_data)?;
112 VarInt(num_remove).encode(&mut component_data)?;
113
114 for _ in 0..num_remove {
116 let id = VarInt::decode(buf)?;
117 id.encode(&mut component_data)?;
118 }
119
120 if num_add > 0 {
121 component_data.extend_from_slice(buf);
125 *buf = &buf[buf.len()..];
126 }
127
128 Ok(Self {
129 item_count,
130 item_id: Some(item_id),
131 component_data,
132 })
133 }
134}
135
136impl EncodedSize for Slot {
138 fn encoded_size(&self) -> usize {
139 let count_size = VarInt(self.item_count).encoded_size();
140 if self.item_count == 0 {
141 count_size
142 } else {
143 count_size
144 + self.item_id.map_or(0, |id| VarInt(id).encoded_size())
145 + if self.component_data.is_empty() {
146 2 } else {
148 self.component_data.len()
149 }
150 }
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn empty_slot_roundtrip() {
160 let slot = Slot::empty();
161 let mut buf = Vec::new();
162 slot.encode(&mut buf).unwrap();
163
164 let mut cursor = buf.as_slice();
165 let decoded = Slot::decode(&mut cursor).unwrap();
166 assert!(decoded.is_empty());
167 assert_eq!(decoded.item_count, 0);
168 }
169
170 #[test]
171 fn empty_slot_encodes_as_zero() {
172 let slot = Slot::empty();
173 let mut buf = Vec::new();
174 slot.encode(&mut buf).unwrap();
175 assert_eq!(buf, [0x00]);
176 }
177
178 #[test]
179 fn simple_slot() {
180 let slot = Slot::new(1, 64);
181 assert!(!slot.is_empty());
182 assert_eq!(slot.item_count, 64);
183 assert_eq!(slot.item_id, Some(1));
184 }
185
186 #[test]
187 fn encoded_size_empty() {
188 let slot = Slot::empty();
189 assert_eq!(slot.encoded_size(), 1);
190 }
191
192 #[test]
193 fn default_is_empty() {
194 let slot = Slot::default();
195 assert!(slot.is_empty());
196 }
197
198 #[test]
199 fn non_empty_slot_encode_decode() {
200 let slot = Slot::new(42, 10);
201 let mut buf = Vec::with_capacity(slot.encoded_size());
202 slot.encode(&mut buf).unwrap();
203 assert_eq!(buf.len(), slot.encoded_size());
204
205 let mut cursor = buf.as_slice();
207 let decoded = Slot::decode(&mut cursor).unwrap();
208 assert_eq!(decoded.item_count, 10);
209 assert_eq!(decoded.item_id, Some(42));
210 }
211
212 #[test]
213 fn encoded_size_non_empty() {
214 let slot = Slot::new(1, 1);
215 assert_eq!(slot.encoded_size(), 4);
218 }
219
220 #[test]
221 fn consecutive_slot_roundtrip() {
222 let slot1 = Slot::new(1, 10);
224 let slot2 = Slot::new(2, 20);
225 let mut buf = Vec::new();
226 slot1.encode(&mut buf).unwrap();
227 slot2.encode(&mut buf).unwrap();
228
229 let mut cursor = buf.as_slice();
230 let d1 = Slot::decode(&mut cursor).unwrap();
231 let d2 = Slot::decode(&mut cursor).unwrap();
232 assert!(cursor.is_empty());
233 assert_eq!(d1.item_count, 10);
234 assert_eq!(d1.item_id, Some(1));
235 assert_eq!(d2.item_count, 20);
236 assert_eq!(d2.item_id, Some(2));
237 }
238
239 #[test]
240 fn slot_with_remove_components_roundtrip() {
241 let mut component_data = Vec::new();
243 VarInt(0).encode(&mut component_data).unwrap(); VarInt(2).encode(&mut component_data).unwrap(); VarInt(5).encode(&mut component_data).unwrap(); VarInt(10).encode(&mut component_data).unwrap(); let slot = Slot {
249 item_count: 1,
250 item_id: Some(42),
251 component_data,
252 };
253 let mut buf = Vec::with_capacity(slot.encoded_size());
254 slot.encode(&mut buf).unwrap();
255 assert_eq!(buf.len(), slot.encoded_size());
256
257 let mut cursor = buf.as_slice();
258 let decoded = Slot::decode(&mut cursor).unwrap();
259 assert!(cursor.is_empty());
260 assert_eq!(decoded.item_count, 1);
261 assert_eq!(decoded.item_id, Some(42));
262 assert_eq!(decoded.component_data, slot.component_data);
263 }
264
265 #[test]
266 fn slot_with_add_components_consumes_remaining() {
267 let mut component_data = Vec::new();
269 VarInt(1).encode(&mut component_data).unwrap(); VarInt(0).encode(&mut component_data).unwrap(); component_data.extend_from_slice(&[0xAA, 0xBB, 0xCC]); let slot = Slot {
274 item_count: 1,
275 item_id: Some(7),
276 component_data,
277 };
278 let mut buf = Vec::with_capacity(slot.encoded_size());
279 slot.encode(&mut buf).unwrap();
280
281 let mut cursor = buf.as_slice();
282 let decoded = Slot::decode(&mut cursor).unwrap();
283 assert!(cursor.is_empty());
284 assert_eq!(decoded.item_count, 1);
285 assert_eq!(decoded.item_id, Some(7));
286 assert_eq!(decoded.component_data, slot.component_data);
287 }
288
289 #[test]
290 fn empty_and_nonempty_slots_interleaved() {
291 let slots = vec![
292 Slot::empty(),
293 Slot::new(1, 5),
294 Slot::empty(),
295 Slot::new(2, 3),
296 ];
297 let mut buf = Vec::new();
298 for s in &slots {
299 s.encode(&mut buf).unwrap();
300 }
301
302 let mut cursor = buf.as_slice();
303 for expected in &slots {
304 let decoded = Slot::decode(&mut cursor).unwrap();
305 assert_eq!(decoded.item_count, expected.item_count);
306 assert_eq!(decoded.item_id, expected.item_id);
307 }
308 assert!(cursor.is_empty());
309 }
310}