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