rpfm_lib/binary/writer.rs
1//---------------------------------------------------------------------------//
2// Copyright (c) 2017-2026 Ismael Gutiérrez González. All rights reserved.
3//
4// This file is part of the Rusted PackFile Manager (RPFM) project,
5// which can be found here: https://github.com/Frodo45127/rpfm.
6//
7// This file is licensed under the MIT license, which can be found here:
8// https://github.com/Frodo45127/rpfm/blob/master/LICENSE.
9//---------------------------------------------------------------------------//
10
11//! Module with the [`WriteBytes`] trait, to write bytes from known types to a [`Writer`].
12//!
13//! [`Writer`]: std::io::Write
14
15use byteorder::{LittleEndian, WriteBytesExt};
16use encoding_rs::ISO_8859_15;
17use half::f16;
18use nalgebra::{Vector2, Vector3, Vector4};
19
20use std::io::Write;
21
22use crate::error::{RLibError, Result};
23
24//---------------------------------------------------------------------------//
25// Trait Definition
26//---------------------------------------------------------------------------//
27
28/// This trait allow us to easily write all kind of data types to something that implements [`Write`].
29pub trait WriteBytes: Write {
30
31 /// This function tries to write a bool value to `self`.
32 ///
33 /// It may fail if `self` cannot be written to.
34 ///
35 /// ```rust
36 /// use std::io::Cursor;
37 ///
38 /// use rpfm_lib::binary::WriteBytes;
39 ///
40 /// let mut data = vec![];
41 /// assert!(data.write_bool(true).is_ok());
42 /// assert_eq!(data, vec![1]);
43 /// ```
44 fn write_bool(&mut self, boolean: bool) -> Result<()> {
45 self.write_u8(u8::from(boolean))
46 }
47
48 /// This function tries to write a byte value to `self`.
49 ///
50 /// It may fail if `self` cannot be written to.
51 ///
52 /// ```rust
53 /// use std::io::Cursor;
54 ///
55 /// use rpfm_lib::binary::WriteBytes;
56 ///
57 /// let mut data = vec![];
58 /// assert!(data.write_u8(10).is_ok());
59 /// assert_eq!(data, vec![10]);
60 /// ```
61 fn write_u8(&mut self, value: u8) -> Result<()> {
62 WriteBytesExt::write_u8(self, value).map_err(From::from)
63 }
64
65 /// This function tries to write an u16 value to `self`.
66 ///
67 /// It may fail if `self` cannot be written to.
68 ///
69 /// ```rust
70 /// use std::io::Cursor;
71 ///
72 /// use rpfm_lib::binary::WriteBytes;
73 ///
74 /// let mut data = vec![];
75 /// assert!(data.write_u16(258).is_ok());
76 /// assert_eq!(data, vec![2, 1]);
77 /// ```
78 fn write_u16(&mut self, integer: u16) -> Result<()> {
79 WriteBytesExt::write_u16::<LittleEndian>(self, integer).map_err(From::from)
80 }
81
82 /// This function tries to write an u24 value to `self`.
83 ///
84 /// It may fail if `self` cannot be written to.
85 ///
86 /// ```rust
87 /// use std::io::Cursor;
88 ///
89 /// use rpfm_lib::binary::WriteBytes;
90 ///
91 /// let mut data = vec![];
92 /// assert!(data.write_u24(8492696).is_ok());
93 /// assert_eq!(data, vec![152, 150, 129]);
94 /// ```
95 fn write_u24(&mut self, integer: u32) -> Result<()> {
96 WriteBytesExt::write_u24::<LittleEndian>(self, integer).map_err(From::from)
97 }
98
99 /// This function tries to write an u32 value to `self`.
100 ///
101 /// It may fail if `self` cannot be written to.
102 ///
103 /// ```rust
104 /// use std::io::Cursor;
105 ///
106 /// use rpfm_lib::binary::WriteBytes;
107 ///
108 /// let mut data = vec![];
109 /// assert!(data.write_u32(258).is_ok());
110 /// assert_eq!(data, vec![2, 1, 0, 0]);
111 /// ```
112 fn write_u32(&mut self, integer: u32) -> Result<()> {
113 WriteBytesExt::write_u32::<LittleEndian>(self, integer).map_err(From::from)
114 }
115
116 /// This function tries to write an u64 value to `self`.
117 ///
118 /// It may fail if `self` cannot be written to.
119 ///
120 /// ```rust
121 /// use std::io::Cursor;
122 ///
123 /// use rpfm_lib::binary::WriteBytes;
124 ///
125 /// let mut data = vec![];
126 /// assert!(data.write_u64(258).is_ok());
127 /// assert_eq!(data, vec![2, 1, 0, 0, 0, 0, 0, 0]);
128 /// ```
129 fn write_u64(&mut self, integer: u64) -> Result<()> {
130 WriteBytesExt::write_u64::<LittleEndian>(self, integer).map_err(From::from)
131 }
132
133 /// This function tries to write an u32 value to `self` as a cauleb128 value.
134 ///
135 /// It may fail if `self` cannot be written to.
136 ///
137 /// ```rust
138 /// use std::io::Cursor;
139 ///
140 /// use rpfm_lib::binary::WriteBytes;
141 ///
142 /// let mut data = vec![];
143 /// assert!(data.write_cauleb128(10, 0).is_ok());
144 /// assert_eq!(data, vec![10]);
145 /// ```
146 fn write_cauleb128(&mut self, mut integer: u32, padding: usize) -> Result<()> {
147 let mut data = vec![];
148
149 loop {
150
151 // Get the byte to encode.
152 let byte = integer & 0x7f;
153
154 // If it's not the last one, encode it with the 0x80 bit set,
155 // and move the rest of the number to be ready to check the next one.
156 data.push(byte as u8 | 0x80);
157 if byte != integer {
158 integer >>= 7;
159 } else {
160 break;
161 }
162 }
163
164 if data.len() < padding {
165 data.resize(padding, 0x80);
166 }
167
168 data.reverse();
169 *data.last_mut().unwrap() &= 0x7f;
170
171 self.write_all(&data).map_err(From::from)
172 }
173
174 /// This function tries to write an i8 value to `self`.
175 ///
176 /// It may fail if `self` cannot be written to.
177 ///
178 /// ```rust
179 /// use std::io::Cursor;
180 ///
181 /// use rpfm_lib::binary::WriteBytes;
182 ///
183 /// let mut data = vec![];
184 /// assert!(data.write_i8(-2).is_ok());
185 /// assert_eq!(data, vec![254]);
186 /// ```
187 fn write_i8(&mut self, integer: i8) -> Result<()> {
188 WriteBytesExt::write_i8(self, integer).map_err(From::from)
189 }
190
191 /// This function tries to write an i16 value to `self`.
192 ///
193 /// It may fail if `self` cannot be written to.
194 ///
195 /// ```rust
196 /// use std::io::Cursor;
197 ///
198 /// use rpfm_lib::binary::WriteBytes;
199 ///
200 /// let mut data = vec![];
201 /// assert!(data.write_i16(-258).is_ok());
202 /// assert_eq!(data, vec![254, 254]);
203 /// ```
204 fn write_i16(&mut self, integer: i16) -> Result<()> {
205 WriteBytesExt::write_i16::<LittleEndian>(self, integer).map_err(From::from)
206 }
207
208 /// This function tries to write an i24 value to `self`.
209 ///
210 /// It may fail if `self` cannot be written to.
211 ///
212 /// ```rust
213 /// use std::io::Cursor;
214 ///
215 /// use rpfm_lib::binary::WriteBytes;
216 ///
217 /// let mut data = vec![];
218 /// assert!(data.write_i24(8_492_696).is_ok());
219 /// assert_eq!(data, vec![152, 150, 129]);
220 /// ```
221 fn write_i24(&mut self, integer: i32) -> Result<()> {
222 WriteBytesExt::write_i24::<LittleEndian>(self, integer).map_err(From::from)
223 }
224
225 /// This function tries to write an i32 value to `self`.
226 ///
227 /// It may fail if `self` cannot be written to.
228 ///
229 /// ```rust
230 /// use std::io::Cursor;
231 ///
232 /// use rpfm_lib::binary::WriteBytes;
233 ///
234 /// let mut data = vec![];
235 /// assert!(data.write_i32(-258).is_ok());
236 /// assert_eq!(data, vec![254, 254, 255, 255]);
237 /// ```
238 fn write_i32(&mut self, integer: i32) -> Result<()> {
239 WriteBytesExt::write_i32::<LittleEndian>(self, integer).map_err(From::from)
240 }
241
242 /// This function tries to write an i64 value to `self`.
243 ///
244 /// It may fail if `self` cannot be written to.
245 ///
246 /// ```rust
247 /// use std::io::Cursor;
248 ///
249 /// use rpfm_lib::binary::WriteBytes;
250 ///
251 /// let mut data = vec![];
252 /// assert!(data.write_i64(-258).is_ok());
253 /// assert_eq!(data, vec![254, 254, 255, 255, 255, 255, 255, 255]);
254 /// ```
255 fn write_i64(&mut self, integer: i64) -> Result<()> {
256 WriteBytesExt::write_i64::<LittleEndian>(self, integer).map_err(From::from)
257 }
258
259 /// This function tries to write an Optional i16 value to `self`.
260 ///
261 /// It may fail if `self` cannot be written to.
262 ///
263 /// ```rust
264 /// use std::io::Cursor;
265 ///
266 /// use rpfm_lib::binary::WriteBytes;
267 ///
268 /// let mut data = vec![];
269 /// assert!(data.write_optional_i16(-258).is_ok());
270 /// assert_eq!(data, vec![1, 254, 254]);
271 /// ```
272 fn write_optional_i16(&mut self, integer: i16) -> Result<()> {
273 self.write_bool(true)?;
274 Self::write_i16(self, integer)
275 }
276
277 /// This function tries to write an Optional i32 value to `self`.
278 ///
279 /// It may fail if `self` cannot be written to.
280 ///
281 /// ```rust
282 /// use std::io::Cursor;
283 ///
284 /// use rpfm_lib::binary::WriteBytes;
285 ///
286 /// let mut data = vec![];
287 /// assert!(data.write_optional_i32(-258).is_ok());
288 /// assert_eq!(data, vec![1, 254, 254, 255, 255]);
289 /// ```
290 fn write_optional_i32(&mut self, integer: i32) -> Result<()> {
291 self.write_bool(true)?;
292 Self::write_i32(self, integer)
293 }
294
295 /// This function tries to write an Optional i64 value to `self`.
296 ///
297 /// It may fail if `self` cannot be written to.
298 ///
299 /// ```rust
300 /// use std::io::Cursor;
301 ///
302 /// use rpfm_lib::binary::WriteBytes;
303 ///
304 /// let mut data = vec![];
305 /// assert!(data.write_optional_i64(-258).is_ok());
306 /// assert_eq!(data, vec![1, 254, 254, 255, 255, 255, 255, 255, 255]);
307 /// ```
308 fn write_optional_i64(&mut self, integer: i64) -> Result<()> {
309 self.write_bool(true)?;
310 Self::write_i64(self, integer)
311 }
312
313 /// This function tries to write a f16 value to `self`.
314 ///
315 /// It may fail if `self` cannot be written to.
316 ///
317 /// ```rust
318 /// use std::io::Cursor;
319 ///
320 /// use rpfm_lib::binary::WriteBytes;
321 ///
322 /// let mut data = vec![];
323 /// assert!(data.write_f16(half::f16::from_f32(-10.2)).is_ok());
324 /// assert_eq!(data, vec![26, 201]);
325 /// ```
326 fn write_f16(&mut self, float: half::f16) -> Result<()> {
327 self.write_u16(float.to_bits())
328 }
329
330 /// This function tries to write a f32 value to `self`.
331 ///
332 /// It may fail if `self` cannot be written to.
333 ///
334 /// ```rust
335 /// use std::io::Cursor;
336 ///
337 /// use rpfm_lib::binary::WriteBytes;
338 ///
339 /// let mut data = vec![];
340 /// assert!(data.write_f32(-10.2).is_ok());
341 /// assert_eq!(data, vec![51, 51, 35, 193]);
342 /// ```
343 fn write_f32(&mut self, float: f32) -> Result<()> {
344 WriteBytesExt::write_f32::<LittleEndian>(self, float).map_err(From::from)
345 }
346
347 /// This function tries to write a normal f32 value to `self`.
348 ///
349 /// It may fail if `self` cannot be written to.
350 ///
351 /// ```rust
352 /// use std::io::Cursor;
353 ///
354 /// use rpfm_lib::binary::WriteBytes;
355 ///
356 /// let mut data = vec![];
357 /// assert!(data.write_f32_normal_as_u8(0.5).is_ok());
358 /// assert_eq!(data, vec![191]);
359 /// ```
360 fn write_f32_normal_as_u8(&mut self, float: f32) -> Result<()> {
361 let value = ((float + 1.0) / 2.0 * 255.0).round() as u8;
362 self.write_u8(value)
363 }
364
365 /// This function tries to write a f64 value to `self`.
366 ///
367 /// It may fail if `self` cannot be written to.
368 ///
369 /// ```rust
370 /// use std::io::Cursor;
371 ///
372 /// use rpfm_lib::binary::WriteBytes;
373 ///
374 /// let mut data = vec![];
375 /// assert!(data.write_f64(-10.2).is_ok());
376 /// assert_eq!(data, vec![102, 102, 102, 102, 102, 102, 36, 192]);
377 /// ```
378 fn write_f64(&mut self, float: f64) -> Result<()> {
379 WriteBytesExt::write_f64::<LittleEndian>(self, float).map_err(From::from)
380 }
381
382 /// This function tries to write an UTF-8 String to `self`.
383 ///
384 /// It may fail if `self` cannot be written to.
385 ///
386 /// ```rust
387 /// use std::io::Cursor;
388 ///
389 /// use rpfm_lib::binary::WriteBytes;
390 ///
391 /// let mut data = vec![];
392 /// assert!(data.write_string_u8("Wahahahaha").is_ok());
393 /// assert_eq!(data, vec![87, 97, 104, 97, 104, 97, 104, 97, 104, 97]);
394 /// ```
395 fn write_string_u8(&mut self, string: &str) -> Result<()> {
396 self.write_all(string.as_bytes()).map_err(From::from)
397 }
398
399 /// This function tries to write an UTF-8 String as an ISO-8859-1 String to `self`.
400 ///
401 /// It may fail if `self` cannot be written to.
402 ///
403 /// ```rust
404 /// use std::io::Cursor;
405 ///
406 /// use rpfm_lib::binary::WriteBytes;
407 ///
408 /// let mut data = vec![];
409 /// assert!(data.write_string_u8_iso_8859_1("Wahaÿhahaha").is_ok());
410 /// assert_eq!(data, vec![87, 97, 104, 97, 255, 104, 97, 104, 97, 104, 97]);
411 /// ```
412 fn write_string_u8_iso_8859_1(&mut self, string: &str) -> Result<()> {
413 let (string, _, _) = ISO_8859_15.encode(string);
414 self.write_all(&string).map_err(From::from)
415 }
416
417 /// This function tries to write an UTF-8 String to `self` as a 00-Padded UTF-8 String with a max size of `size`.
418 ///
419 /// It may fail if `self` cannot be written to. If `crop` is true, in case the string is longer than the size
420 /// the string will be cropped to fit in the size we have. If it's false, an error will be returned.
421 ///
422 /// ```rust
423 /// use std::io::Cursor;
424 ///
425 /// use rpfm_lib::binary::WriteBytes;
426 ///
427 /// let mut data = vec![];
428 /// assert!(data.write_string_u8_0padded("Waha", 8, false).is_ok());
429 /// assert_eq!(data, vec![87, 97, 104, 97, 0, 0, 0, 0]);
430 /// ```
431 fn write_string_u8_0padded(&mut self, string: &str, size: usize, crop: bool) -> Result<()> {
432 if string.len() > size {
433 if crop {
434 let mut string = string.to_owned();
435 string.truncate(size);
436 self.write_string_u8(&string)?;
437 self.write_all(&vec![0; size - string.len()]).map_err(From::from)
438 } else {
439 Err(RLibError::EncodingPaddedStringError("UTF-8 0-Padded String".to_owned(), string.to_owned(), string.len(), size))
440 }
441 }
442
443 else {
444 self.write_string_u8(string)?;
445 self.write_all(&vec![0; size - string.len()]).map_err(From::from)
446 }
447 }
448
449 /// This function tries to write an UTF-8 String to `self` as a 00-Terminated (or NULL-Terminated) UTF-8 String.
450 ///
451 /// It may fail if `self` cannot be written to.
452 ///
453 /// ```rust
454 /// use std::io::Cursor;
455 ///
456 /// use rpfm_lib::binary::WriteBytes;
457 ///
458 /// let mut data = vec![];
459 /// assert!(data.write_string_u8_0terminated("Wahahaha").is_ok());
460 /// assert_eq!(data, vec![87, 97, 104, 97, 104, 97, 104, 97, 0]);
461 /// ```
462 fn write_string_u8_0terminated(&mut self, string: &str) -> Result<()> {
463 self.write_string_u8(string)?;
464 Self::write_u8(self, 0)
465 }
466
467 /// This function tries to write an UTF-8 String to `self` as a Sized UTF-8 String.
468 ///
469 /// It may fail if `self` cannot be written to.
470 ///
471 /// ```rust
472 /// use std::io::Cursor;
473 ///
474 /// use rpfm_lib::binary::WriteBytes;
475 ///
476 /// let mut data = vec![];
477 /// assert!(data.write_sized_string_u8("Wahaha").is_ok());
478 /// assert_eq!(data, vec![6, 0, 87, 97, 104, 97, 104, 97]);
479 /// ```
480 fn write_sized_string_u8(&mut self, string: &str) -> Result<()> {
481 self.write_u16(string.len() as u16)?;
482 self.write_string_u8(string)
483 }
484
485 /// This function tries to write an UTF-8 String to `self` as a Sized UTF-8 String, with a 4 byte size.
486 ///
487 /// It may fail if `self` cannot be written to.
488 ///
489 /// ```rust
490 /// use std::io::Cursor;
491 ///
492 /// use rpfm_lib::binary::WriteBytes;
493 ///
494 /// let mut data = vec![];
495 /// assert!(data.write_sized_string_u8_u32("Wahaha").is_ok());
496 /// assert_eq!(data, vec![6, 0, 0, 0, 87, 97, 104, 97, 104, 97]);
497 /// ```
498 fn write_sized_string_u8_u32(&mut self, string: &str) -> Result<()> {
499 self.write_u32(string.len() as u32)?;
500 self.write_string_u8(string)
501 }
502
503 /// This function tries to write an UTF-8 String to `self` as an Optional UTF-8 String.
504 ///
505 /// It may fail if `self` cannot be written to.
506 ///
507 /// ```rust
508 /// use std::io::Cursor;
509 ///
510 /// use rpfm_lib::binary::WriteBytes;
511 ///
512 /// let mut data = vec![];
513 /// assert!(data.write_optional_string_u8("Wahaha").is_ok());
514 /// assert_eq!(data, vec![1, 6, 0, 87, 97, 104, 97, 104, 97]);
515 /// ```
516 fn write_optional_string_u8(&mut self, string: &str) -> Result<()> {
517 if string.is_empty() {
518 self.write_bool(false)
519 }
520 else {
521 self.write_bool(true)?;
522 self.write_u16(string.len() as u16)?;
523 self.write_string_u8(string)
524 }
525 }
526
527 /// This function tries to write an UTF-8 String to `self` as an UTF-16 String.
528 ///
529 /// It may fail if `self` cannot be written to.
530 ///
531 /// ```rust
532 /// use std::io::Cursor;
533 ///
534 /// use rpfm_lib::binary::WriteBytes;
535 ///
536 /// let mut data = vec![];
537 /// assert!(data.write_string_u16("Wahaha").is_ok());
538 /// assert_eq!(data, vec![87, 0, 97, 0, 104, 0, 97, 0, 104, 0, 97, 0]);
539 /// ```
540 fn write_string_u16(&mut self, string: &str) -> Result<()> {
541 string.encode_utf16().try_for_each(|character| self.write_u16(character))
542 }
543
544 /// This function tries to write an UTF-8 String to `self` as a 00-Padded UTF-16 String with a max size of `size`.
545 ///
546 /// It may fail if `self` cannot be written to. If `crop` is true, in case the string is longer than the size
547 /// the string will be cropped to fit in the size we have. If it's false, an error will be returned.
548 ///
549 /// ```rust
550 /// use std::io::Cursor;
551 ///
552 /// use rpfm_lib::binary::WriteBytes;
553 ///
554 /// let mut data = vec![];
555 /// assert!(data.write_string_u16_0padded("Waha", 16, false).is_ok());
556 /// assert_eq!(data, vec![87, 0, 97, 0, 104, 0, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
557 /// ```
558 fn write_string_u16_0padded(&mut self, string: &str, size: usize, crop: bool) -> Result<()> {
559 if string.len() * 2 > size {
560 if crop {
561 let mut string = string.to_owned();
562 string.truncate(size);
563 self.write_string_u16(&string)?;
564 self.write_all(&vec![0; size - (string.len() * 2)]).map_err(From::from)
565 } else {
566 Err(RLibError::EncodingPaddedStringError("UTF-16 0-Padded String".to_owned(), string.to_string(), string.len(), size))
567 }
568 }
569
570 else {
571 self.write_string_u16(string)?;
572 self.write_all(&vec![0; size - (string.len() * 2)]).map_err(From::from)
573 }
574 }
575
576 /// This function tries to write an UTF-8 String to `self` as a Sized UTF-16 String.
577 ///
578 /// It may fail if `self` cannot be written to.
579 ///
580 /// ```rust
581 /// use std::io::Cursor;
582 ///
583 /// use rpfm_lib::binary::WriteBytes;
584 ///
585 /// let mut data = vec![];
586 /// assert!(data.write_sized_string_u16("¡Bebes mejor de lo que luchas, Zhang Fei!").is_ok());
587 /// assert_eq!(data, vec![0x29, 0x00, 0xA1, 0x00, 0x42, 0x00, 0x65, 0x00, 0x62, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x6A, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x71, 0x00, 0x75, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x75, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x73, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x5A, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x20, 0x00, 0x46, 0x00, 0x65, 0x00, 0x69, 0x00, 0x21, 0x00]);
588 /// ```
589 fn write_sized_string_u16(&mut self, string: &str) -> Result<()> {
590 self.write_u16(string.encode_utf16().count() as u16)?;
591 self.write_string_u16(string)
592 }
593
594 /// This function tries to write an UTF-8 String to `self` as a Sized UTF-16 String, with a four-byte size.
595 ///
596 /// It may fail if `self` cannot be written to.
597 ///
598 /// ```rust
599 /// use std::io::Cursor;
600 ///
601 /// use rpfm_lib::binary::WriteBytes;
602 ///
603 /// let mut data = vec![];
604 /// assert!(data.write_sized_string_u16_u32("¡Bebes mejor de lo que luchas, Zhang Fei!").is_ok());
605 /// assert_eq!(data, vec![0x29, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x42, 0x00, 0x65, 0x00, 0x62, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x6A, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x71, 0x00, 0x75, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x75, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x73, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x5A, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x20, 0x00, 0x46, 0x00, 0x65, 0x00, 0x69, 0x00, 0x21, 0x00]);
606 /// ```
607 fn write_sized_string_u16_u32(&mut self, string: &str) -> Result<()> {
608 self.write_u32(string.encode_utf16().count() as u32)?;
609 self.write_string_u16(string)
610 }
611
612 /// This function tries to write an UTF-8 String to `self` as an Optional UTF-16 String.
613 ///
614 /// It may fail if `self` cannot be written to.
615 ///
616 /// ```rust
617 /// use std::io::Cursor;
618 ///
619 /// use rpfm_lib::binary::WriteBytes;
620 ///
621 /// let mut data = vec![];
622 /// assert!(data.write_optional_string_u16("Waha").is_ok());
623 /// assert_eq!(data, vec![1, 4, 0, 87, 0, 97, 0, 104, 0, 97, 0]);
624 /// ```
625 fn write_optional_string_u16(&mut self, string: &str) -> Result<()> {
626 if string.is_empty() {
627 self.write_bool(false)
628 }
629 else {
630 self.write_bool(true)?;
631 self.write_u16(string.encode_utf16().count() as u16)?;
632 self.write_string_u16(string)
633 }
634 }
635
636 /// This function tries to write an UTF-8 String representing a Hex-Encoded RGB Colour to `self`.
637 ///
638 /// It may fail if `self` cannot be written to or if the string is not a valid Hex-Encoded RGB Colour.
639 ///
640 /// ```rust
641 /// use std::io::Cursor;
642 ///
643 /// use rpfm_lib::binary::WriteBytes;
644 ///
645 /// let mut data = vec![];
646 /// assert!(data.write_string_colour_rgb("0504FF").is_ok());
647 /// assert_eq!(data, vec![0xFF, 0x04, 0x05, 0x00]);
648 /// ```
649 fn write_string_colour_rgb(&mut self, value: &str) -> Result<()> {
650 let value = u32::from_str_radix(value, 16)?;
651 self.write_u32(value)
652 }
653
654 /// This function tries to write an Vector of 2 u8 to `self`.
655 ///
656 /// It may fail if `self` cannot be written to.
657 ///
658 /// ```rust
659 /// use nalgebra::Vector2;
660 /// use std::io::Cursor;
661 ///
662 /// use rpfm_lib::binary::WriteBytes;
663 ///
664 /// let mut data = vec![];
665 /// assert!(data.write_vector_2_u8(Vector2::new(10, 10)).is_ok());
666 /// assert_eq!(data, vec![0x0A, 0x0A]);
667 /// ```
668 fn write_vector_2_u8(&mut self, value: Vector2<u8>) -> Result<()> {
669 self.write_u8(value.x)?;
670 self.write_u8(value.y)?;
671
672 Ok(())
673 }
674
675 /// This function tries to write an Vector of 2 f32 converted to 2 u8 to `self`.
676 ///
677 /// It may fail if `self` cannot be written to.
678 ///
679 /// ```rust
680 /// use nalgebra::Vector2;
681 /// use std::io::Cursor;
682 ///
683 /// use rpfm_lib::binary::WriteBytes;
684 ///
685 /// let mut data = vec![];
686 /// assert!(data.write_vector_2_f32_pct_as_vector_2_u8(Vector2::new(0.039215688, 0.039215688)).is_ok());
687 /// assert_eq!(data, vec![0x0A, 0x0A]);
688 /// ```
689 fn write_vector_2_f32_pct_as_vector_2_u8(&mut self, value: Vector2<f32>) -> Result<()> {
690 self.write_u8((value.x * 255.0) as u8)?;
691 self.write_u8((value.y * 255.0) as u8)?;
692
693 Ok(())
694 }
695
696 /// This function tries to write an Vector of 2 f32 converted to 2 f16 to `self`.
697 ///
698 /// It may fail if `self` cannot be written to.
699 ///
700 /// ```rust
701 /// use nalgebra::Vector2;
702 /// use std::io::Cursor;
703 ///
704 /// use rpfm_lib::binary::WriteBytes;
705 ///
706 /// let mut data = vec![];
707 /// assert!(data.write_vector_2_f32_as_vector_2_f16(Vector2::new(0.00018429756, 0.00018429756)).is_ok());
708 /// assert_eq!(data, vec![0x0A, 0x0A, 0x0A, 0x0A]);
709 /// ```
710 fn write_vector_2_f32_as_vector_2_f16(&mut self, value: Vector2<f32>) -> Result<()> {
711 self.write_f16(f16::from_f32(value.x))?;
712 self.write_f16(f16::from_f32(value.y))?;
713
714 Ok(())
715 }
716
717 /// This function tries to write an Vector of 3 normalized f32 converted to 4 u8 to `self`.
718 ///
719 /// It may fail if `self` cannot be written to.
720 ///
721 /// ```rust
722 /// use nalgebra::Vector3;
723 /// use std::io::Cursor;
724 ///
725 /// use rpfm_lib::binary::WriteBytes;
726 ///
727 /// let mut data = vec![];
728 /// assert!(data.write_vector_3_f32_normal_as_vector_4_u8(Vector3::new(-0.92156863, -0.92156863, -0.92156863)).is_ok());
729 /// assert_eq!(data, vec![0x0A, 0x0A, 0x0A, 0x00]);
730 /// ```
731 fn write_vector_3_f32_normal_as_vector_4_u8(&mut self, value: Vector3<f32>) -> Result<()> {
732 self.write_f32_normal_as_u8(value.x)?;
733 self.write_f32_normal_as_u8(value.y)?;
734 self.write_f32_normal_as_u8(value.z)?;
735 self.write_f32_normal_as_u8(-1.0)?;
736
737 Ok(())
738 }
739
740 /// This function tries to write an Vector of 4 u8 to `self`.
741 ///
742 /// It may fail if `self` cannot be written to.
743 ///
744 /// ```rust
745 /// use nalgebra::Vector4;
746 /// use std::io::Cursor;
747 ///
748 /// use rpfm_lib::binary::WriteBytes;
749 ///
750 /// let mut data = vec![];
751 /// assert!(data.write_vector_4_u8(Vector4::new(10, 10, 10, 10)).is_ok());
752 /// assert_eq!(data, vec![0x0A, 0x0A, 0x0A, 0x0A]);
753 /// ```
754 fn write_vector_4_u8(&mut self, value: Vector4<u8>) -> Result<()> {
755 self.write_u8(value.x)?;
756 self.write_u8(value.y)?;
757 self.write_u8(value.z)?;
758 self.write_u8(value.w)?;
759
760 Ok(())
761 }
762
763 /// This function tries to write an Vector of 4 f32 to `self`.
764 ///
765 /// It may fail if `self` cannot be written to.
766 ///
767 /// ```rust
768 /// use nalgebra::Vector4;
769 /// use std::io::Cursor;
770 ///
771 /// use rpfm_lib::binary::WriteBytes;
772 ///
773 /// let mut data = vec![];
774 /// assert!(data.write_vector_4_f32(Vector4::new(10.0, 10.0, 10.0, 10.0)).is_ok());
775 /// assert_eq!(data, vec![0, 0, 32, 65, 0, 0, 32, 65, 0, 0, 32, 65, 0, 0, 32, 65]);
776 /// ```
777 fn write_vector_4_f32(&mut self, value: Vector4<f32>) -> Result<()> {
778 self.write_f32(value.x)?;
779 self.write_f32(value.y)?;
780 self.write_f32(value.z)?;
781 self.write_f32(value.w)?;
782
783 Ok(())
784 }
785
786 /// This function tries to write an Vector of 4 f32 to a Vector of 3 f32 to `self`.
787 ///
788 /// It may fail if `self` cannot be written to.
789 ///
790 /// ```rust
791 /// use nalgebra::Vector4;
792 /// use std::io::Cursor;
793 ///
794 /// use rpfm_lib::binary::WriteBytes;
795 ///
796 /// let mut data = vec![];
797 /// assert!(data.write_vector_4_f32_to_vector_3_f32(Vector4::new(10.0, 10.0, 10.0, 0.0)).is_ok());
798 /// assert_eq!(data, vec![0, 0, 32, 65, 0, 0, 32, 65, 0, 0, 32, 65]);
799 /// ```
800 fn write_vector_4_f32_to_vector_3_f32(&mut self, value: Vector4<f32>) -> Result<()> {
801 self.write_f32(value.x)?;
802 self.write_f32(value.y)?;
803 self.write_f32(value.z)?;
804
805 Ok(())
806 }
807
808 /// This function tries to write an Vector of 4 f32 as percentage converted to 4 u8 to `self`.
809 ///
810 /// It may fail if `self` cannot be written to.
811 ///
812 /// ```rust
813 /// use nalgebra::Vector4;
814 /// use std::io::Cursor;
815 ///
816 /// use rpfm_lib::binary::WriteBytes;
817 ///
818 /// let mut data = vec![];
819 /// assert!(data.write_vector_4_f32_pct_as_vector_4_u8(Vector4::new(0.039215688, 0.039215688, 0.039215688, 0.039215688)).is_ok());
820 /// assert_eq!(data, vec![0x0A, 0x0A, 0x0A, 0x0A]);
821 /// ```
822 fn write_vector_4_f32_pct_as_vector_4_u8(&mut self, value: Vector4<f32>) -> Result<()> {
823 self.write_u8((value.x * 255.0) as u8)?;
824 self.write_u8((value.y * 255.0) as u8)?;
825 self.write_u8((value.z * 255.0) as u8)?;
826 self.write_u8((value.w * 255.0) as u8)?;
827
828 Ok(())
829 }
830
831
832 /// This function tries to write an Vector of 4 normalized f32 converted to 4 u8 to `self`.
833 ///
834 /// It may fail if `self` cannot be written to.
835 ///
836 /// ```rust
837 /// use nalgebra::Vector4;
838 /// use std::io::Cursor;
839 ///
840 /// use rpfm_lib::binary::WriteBytes;
841 ///
842 /// let mut data = vec![];
843 /// assert!(data.write_vector_4_f32_normal_as_vector_4_u8(Vector4::new(-0.92156863, -0.92156863, -0.92156863, -0.92156863)).is_ok());
844 /// assert_eq!(data, vec![0x0A, 0x0A, 0x0A, 0x0A]);
845 /// ```
846 fn write_vector_4_f32_normal_as_vector_4_u8(&mut self, value: Vector4<f32>) -> Result<()> {
847 self.write_f32_normal_as_u8(value.x)?;
848 self.write_f32_normal_as_u8(value.y)?;
849 self.write_f32_normal_as_u8(value.z)?;
850 self.write_f32_normal_as_u8(value.w)?;
851
852 Ok(())
853 }
854
855 /// This function tries to write an Vector of 4 normalized f32 converted to 4 f16 to `self`.
856 ///
857 /// It may fail if `self` cannot be written to.
858 ///
859 /// ```rust
860 /// use nalgebra::Vector4;
861 /// use std::io::Cursor;
862 ///
863 /// use rpfm_lib::binary::WriteBytes;
864 ///
865 /// let mut data = vec![];
866 /// assert!(data.write_vector_4_f32_normal_as_vector_4_f16(Vector4::new(3.096775, 3.096775, 3.096775, 1.7597656)).is_ok());
867 /// assert_eq!(data, vec![
868 /// 0x0A, 0x3F,
869 /// 0x0A, 0x3F,
870 /// 0x0A, 0x3F,
871 /// 0x0A, 0x3F
872 /// ]);
873 /// ```
874 fn write_vector_4_f32_normal_as_vector_4_f16(&mut self, value: Vector4<f32>) -> Result<()> {
875 let mut x = value.x;
876 let mut y = value.y;
877 let mut z = value.z;
878 let w = value.w;
879
880 if w != 0.0 {
881 x /= w;
882 y /= w;
883 z /= w;
884 }
885
886 self.write_f16(f16::from_f32(x))?;
887 self.write_f16(f16::from_f32(y))?;
888 self.write_f16(f16::from_f32(z))?;
889 self.write_f16(f16::from_f32(w))?;
890
891 Ok(())
892 }
893}
894
895// Automatic implementation for everything that implements `Write`.
896impl<W: Write> WriteBytes for W {}