steel_protocol/packets/game/
s_rename_item.rs1use std::io::Cursor;
4
5use steel_macros::ServerPacket;
6use steel_utils::serial::{ReadFrom, prefixed_read::read_utf};
7
8const MAX_PACKET_NAME_LENGTH: usize = 32_767;
9
10#[derive(ServerPacket, Clone, Debug)]
12pub struct SRenameItem {
13 pub name: String,
15}
16
17impl ReadFrom for SRenameItem {
18 fn read(data: &mut Cursor<&[u8]>) -> std::io::Result<Self> {
19 Ok(Self {
20 name: read_utf(data, MAX_PACKET_NAME_LENGTH)?,
21 })
22 }
23}
24
25#[cfg(test)]
26mod tests {
27 use steel_utils::{
28 codec::VarInt,
29 serial::{ReadFrom as _, WriteTo as _},
30 };
31
32 use super::{MAX_PACKET_NAME_LENGTH, SRenameItem};
33
34 fn encoded_string(bytes: &[u8]) -> Vec<u8> {
35 let mut encoded = Vec::with_capacity(VarInt::MAX_SIZE + bytes.len());
36 VarInt(bytes.len() as i32)
37 .write(&mut encoded)
38 .expect("test string length should encode");
39 encoded.extend_from_slice(bytes);
40 encoded
41 }
42
43 fn decode(bytes: &[u8]) -> std::io::Result<SRenameItem> {
44 SRenameItem::read(&mut std::io::Cursor::new(bytes))
45 }
46
47 #[test]
48 fn accepts_vanilla_utf16_boundary() {
49 let name = "a".repeat(MAX_PACKET_NAME_LENGTH);
50 let decoded = decode(&encoded_string(name.as_bytes()))
51 .expect("the Vanilla UTF-16 boundary should decode");
52 assert_eq!(decoded.name, name);
53 }
54
55 #[test]
56 fn rejects_more_than_vanilla_utf16_boundary() {
57 let name = "a".repeat(MAX_PACKET_NAME_LENGTH + 1);
58 assert!(decode(&encoded_string(name.as_bytes())).is_err());
59 }
60
61 #[test]
62 fn accepts_multibyte_name_above_the_old_byte_bound() {
63 let name = format!("{}X", "ยง".repeat(16_251));
64 assert_eq!(name.encode_utf16().count(), 16_252);
65 assert_eq!(name.len(), 32_503);
66
67 let decoded =
68 decode(&encoded_string(name.as_bytes())).expect("Vanilla accepts this packet name");
69 assert_eq!(decoded.name, name);
70 }
71
72 #[test]
73 fn rejects_encoded_length_above_vanilla_maximum() {
74 let bytes = vec![b'a'; MAX_PACKET_NAME_LENGTH * 3 + 1];
75 assert!(decode(&encoded_string(&bytes)).is_err());
76 }
77
78 #[test]
79 fn malformed_utf8_uses_replacement_characters() {
80 let decoded = decode(&encoded_string(&[0xFF]))
81 .expect("Vanilla decodes malformed UTF-8 with replacement");
82 assert_eq!(decoded.name, "\u{FFFD}");
83 }
84
85 #[test]
86 fn malformed_surrogate_sequence_uses_one_replacement_character() {
87 let decoded = decode(&encoded_string(&[0xED, 0xA0, 0x80]))
88 .expect("Vanilla replaces the complete malformed surrogate sequence");
89 assert_eq!(decoded.name, "\u{FFFD}");
90 }
91}