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::{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 {}