Skip to main content

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