steel_utils/serial/
write.rs1#![expect(
2 clippy::disallowed_types,
3 reason = "HashMap is used directly to implement WriteTo; project types are not available here"
4)]
5use std::{
6 collections::HashMap,
7 hash::BuildHasher,
8 io::{Error, Result, Write},
9};
10
11use simdnbt::owned::{NbtCompound, NbtTag};
12use text_components::TextComponent;
13use uuid::Uuid;
14
15use crate::{
16 BlockPos, Identifier, PackedBlockPos,
17 codec::VarInt,
18 serial::{DEFAULT_BOUND, PrefixedWrite, WriteTo},
19};
20
21impl WriteTo for bool {
22 fn write(&self, writer: &mut impl Write) -> Result<()> {
23 u8::from(*self).write(writer)?;
24 Ok(())
25 }
26}
27
28impl WriteTo for u8 {
29 fn write(&self, writer: &mut impl Write) -> Result<()> {
30 writer.write_all(&self.to_be_bytes())
31 }
32
33 fn write_slice(values: &[Self], writer: &mut impl Write) -> Result<()> {
34 writer.write_all(values)
35 }
36}
37
38impl WriteTo for u16 {
39 fn write(&self, writer: &mut impl Write) -> Result<()> {
40 writer.write_all(&self.to_be_bytes())
41 }
42}
43
44impl WriteTo for u32 {
45 fn write(&self, writer: &mut impl Write) -> Result<()> {
46 writer.write_all(&self.to_be_bytes())
47 }
48}
49
50impl WriteTo for u64 {
51 fn write(&self, writer: &mut impl Write) -> Result<()> {
52 writer.write_all(&self.to_be_bytes())
53 }
54}
55
56impl WriteTo for i8 {
57 fn write(&self, writer: &mut impl Write) -> Result<()> {
58 writer.write_all(&self.to_be_bytes())
59 }
60}
61
62impl WriteTo for i16 {
63 fn write(&self, writer: &mut impl Write) -> Result<()> {
64 writer.write_all(&self.to_be_bytes())
65 }
66}
67
68impl WriteTo for i32 {
69 fn write(&self, writer: &mut impl Write) -> Result<()> {
70 writer.write_all(&self.to_be_bytes())
71 }
72}
73
74impl WriteTo for i64 {
75 fn write(&self, writer: &mut impl Write) -> Result<()> {
76 writer.write_all(&self.to_be_bytes())
77 }
78}
79
80impl WriteTo for f32 {
81 fn write(&self, writer: &mut impl Write) -> Result<()> {
82 writer.write_all(&self.to_be_bytes())
83 }
84}
85
86impl WriteTo for f64 {
87 fn write(&self, writer: &mut impl Write) -> Result<()> {
88 writer.write_all(&self.to_be_bytes())
89 }
90}
91
92impl<T: WriteTo> WriteTo for Option<T> {
93 fn write(&self, writer: &mut impl Write) -> Result<()> {
94 if let Some(value) = self {
95 true.write(writer)?;
96 value.write(writer)
97 } else {
98 false.write(writer)
99 }
100 }
101}
102
103impl<T: WriteTo, const N: usize> WriteTo for [T; N] {
104 fn write(&self, writer: &mut impl Write) -> Result<()> {
105 T::write_slice(self, writer)
106 }
107}
108
109impl<T: WriteTo, Z: WriteTo> WriteTo for (T, Z) {
110 fn write(&self, writer: &mut impl Write) -> Result<()> {
111 self.0.write(writer)?;
112 self.1.write(writer)
113 }
114}
115
116impl<K: WriteTo, V: WriteTo, S: BuildHasher> WriteTo for HashMap<K, V, S> {
117 fn write(&self, writer: &mut impl Write) -> Result<()> {
118 VarInt(self.len() as i32).write(writer)?;
119 for (key, value) in self {
120 key.write(writer)?;
121 value.write(writer)?;
122 }
123 Ok(())
124 }
125}
126
127impl<T: WriteTo> WriteTo for Vec<T> {
128 fn write(&self, writer: &mut impl Write) -> Result<()> {
129 self.write_prefixed::<VarInt>(writer)
130 }
131}
132
133impl WriteTo for BlockPos {
134 fn write(&self, writer: &mut impl Write) -> Result<()> {
135 PackedBlockPos::from(*self).write(writer)
136 }
137}
138
139impl WriteTo for TextComponent {
140 fn write(&self, writer: &mut impl Write) -> Result<()> {
141 WriteTo::write(&self.to_codec_nbt(), writer)
142 }
143}
144
145impl WriteTo for Uuid {
146 fn write(&self, writer: &mut impl Write) -> Result<()> {
147 let (most_significant_bits, least_significant_bits) = self.as_u64_pair();
148 most_significant_bits.write(writer)?;
149 least_significant_bits.write(writer)?;
150 Ok(())
151 }
152}
153
154impl WriteTo for Identifier {
155 fn write(&self, writer: &mut impl Write) -> Result<()> {
156 let len = self.namespace.len() + 1 + self.path.len();
157 if len > DEFAULT_BOUND {
158 return Err(Error::other("Too long"));
159 }
160
161 VarInt(len as i32).write(writer)?;
162 writer.write_all(self.namespace.as_bytes())?;
163 writer.write_all(b":")?;
164 writer.write_all(self.path.as_bytes())
165 }
166}
167
168impl WriteTo for NbtTag {
169 fn write(&self, writer: &mut impl Write) -> Result<()> {
170 let mut buf = Vec::new();
171 self.write(&mut buf);
172 writer.write_all(&buf)?;
173 Ok(())
174 }
175}
176
177impl WriteTo for NbtCompound {
178 fn write(&self, writer: &mut impl Write) -> Result<()> {
179 let mut buf = Vec::new();
180 self.write(&mut buf);
181 writer.write_all(&buf)?;
182 Ok(())
183 }
184}
185
186#[derive(Debug, Clone)]
193pub struct OptionalNbt(pub Option<NbtCompound>);
194
195impl WriteTo for OptionalNbt {
196 fn write(&self, writer: &mut impl Write) -> Result<()> {
197 match &self.0 {
198 Some(compound) => {
199 writer.write_all(&[0x0A])?;
202 let mut buf = Vec::new();
203 compound.write(&mut buf);
204 writer.write_all(&buf)?;
205 }
206 None => {
207 writer.write_all(&[0x00])?;
209 }
210 }
211 Ok(())
212 }
213}
214
215impl From<Option<NbtCompound>> for OptionalNbt {
216 fn from(opt: Option<NbtCompound>) -> Self {
217 Self(opt)
218 }
219}