|
1 | 1 | use crate::{
|
2 | 2 | common::PdsDateFormatter,
|
3 | 3 | text::{ArrayReader, ObjectReader, Operator, ValueReader},
|
4 |
| - Encoding, Error, ErrorKind, TextTape, TextToken, |
| 4 | + BinaryToken, Encoding, Error, ErrorKind, TextTape, TextToken, |
5 | 5 | };
|
6 | 6 | use std::{fmt::Arguments, io::Write, ops::Deref};
|
7 | 7 |
|
|
89 | 89 | }
|
90 | 90 |
|
91 | 91 | /// Returns true if the next write event would be a key
|
| 92 | + #[inline] |
92 | 93 | pub fn expecting_key(&self) -> bool {
|
93 |
| - self.state == WriteState::Key || self.state == WriteState::FirstKey |
| 94 | + matches!(self.state, WriteState::Key | WriteState::FirstKey) |
| 95 | + } |
| 96 | + |
| 97 | + /// Returns the number of objects deep the writer is from the root object |
| 98 | + #[inline] |
| 99 | + pub fn depth(&self) -> usize { |
| 100 | + self.depth.len() |
94 | 101 | }
|
95 | 102 |
|
96 | 103 | /// Write out the start of an object
|
@@ -294,6 +301,23 @@ where
|
294 | 301 | write!(self, "{}", data)
|
295 | 302 | }
|
296 | 303 |
|
| 304 | + /// Write a signed 64bit integer. |
| 305 | + /// |
| 306 | + /// ``` |
| 307 | + /// use jomini::TextWriterBuilder; |
| 308 | + /// # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 309 | + /// let mut out: Vec<u8> = Vec::new(); |
| 310 | + /// let mut writer = TextWriterBuilder::new().from_writer(&mut out); |
| 311 | + /// writer.write_unquoted(b"ratio")?; |
| 312 | + /// writer.write_i64(-1); |
| 313 | + /// assert_eq!(&out, b"ratio=-1"); |
| 314 | + /// # Ok(()) |
| 315 | + /// # } |
| 316 | + /// ``` |
| 317 | + pub fn write_i64(&mut self, data: i64) -> Result<(), Error> { |
| 318 | + write!(self, "{}", data) |
| 319 | + } |
| 320 | + |
297 | 321 | /// Write a 32 bit floating point at full precision
|
298 | 322 | ///
|
299 | 323 | /// ```
|
@@ -491,6 +515,80 @@ where
|
491 | 515 | self.mixed_mode = MixedMode::Started;
|
492 | 516 | }
|
493 | 517 |
|
| 518 | + /// Write the binary token with reasonable defaults |
| 519 | + /// |
| 520 | + /// This function is intended to be used as a fallback for a higher level |
| 521 | + /// melter that doesn't need special handling for a given token and thus can |
| 522 | + /// rely on the default behavior of forwarding the token to the writer's |
| 523 | + /// `write_x` methods. |
| 524 | + /// |
| 525 | + /// Any caller that uses this function will want to provide the floating |
| 526 | + /// point conversion and token translation, which is different from game to |
| 527 | + /// game. |
| 528 | + /// |
| 529 | + /// ## Example |
| 530 | + /// |
| 531 | + /// ``` |
| 532 | + /// use jomini::{binary::{BinaryTape, BinaryToken}, TextTape, TextWriterBuilder}; |
| 533 | + /// |
| 534 | + /// let data = [ 0x82, 0x2d, 0x01, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x45, 0x4e, 0x47 ]; |
| 535 | + /// let tape = BinaryTape::from_slice(&data[..]).unwrap(); |
| 536 | + /// let mut out: Vec<u8> = Vec::new(); |
| 537 | + /// let mut writer = TextWriterBuilder::new().from_writer(&mut out); |
| 538 | + /// for token in tape.tokens() { |
| 539 | + /// match token { |
| 540 | + /// // Define a floating point handler as there isn't a fallback format |
| 541 | + /// BinaryToken::F32(x) => writer.write_f32(f32::from_le_bytes(*x))?, |
| 542 | + /// BinaryToken::F64(x) => writer.write_f64(f64::from_le_bytes(*x))?, |
| 543 | + /// |
| 544 | + /// // Every melter will want a custom token resolver |
| 545 | + /// BinaryToken::Token(x) => { |
| 546 | + /// if *x == 0x2d82 { |
| 547 | + /// writer.write_unquoted(b"field1")?; |
| 548 | + /// } else { |
| 549 | + /// writer.write_unquoted(b"unknown")?; |
| 550 | + /// } |
| 551 | + /// }, |
| 552 | + /// x => writer.write_binary(x)?, |
| 553 | + /// } |
| 554 | + /// } |
| 555 | + /// assert_eq!(&out, b"field1=\"ENG\""); |
| 556 | + /// # Ok::<(), Box<dyn std::error::Error>>(()) |
| 557 | + /// ``` |
| 558 | + #[inline] |
| 559 | + pub fn write_binary(&mut self, token: &BinaryToken<'_>) -> Result<(), Error> { |
| 560 | + match token { |
| 561 | + BinaryToken::Array(_) => self.write_array_start(), |
| 562 | + BinaryToken::Object(_) => self.write_object_start(), |
| 563 | + BinaryToken::MixedContainer => { |
| 564 | + self.start_mixed_mode(); |
| 565 | + Ok(()) |
| 566 | + } |
| 567 | + BinaryToken::Equal => self.write_operator(Operator::Equal), |
| 568 | + BinaryToken::End(_) => self.write_end(), |
| 569 | + BinaryToken::Bool(x) => self.write_bool(*x), |
| 570 | + BinaryToken::U32(x) => self.write_u32(*x), |
| 571 | + BinaryToken::U64(x) => self.write_u64(*x), |
| 572 | + BinaryToken::I64(x) => self.write_i64(*x), |
| 573 | + BinaryToken::I32(x) => self.write_i32(*x), |
| 574 | + BinaryToken::Quoted(x) => self.write_quoted(x.as_bytes()), |
| 575 | + BinaryToken::Unquoted(x) => self.write_unquoted(x.as_bytes()), |
| 576 | + BinaryToken::F32(x) => self.write_f32(f32::from_le_bytes(*x)), |
| 577 | + BinaryToken::F64(x) => self.write_f64(f64::from_le_bytes(*x)), |
| 578 | + BinaryToken::Token(x) => { |
| 579 | + write!(self, "__unknown_0x{:x}", x) |
| 580 | + } |
| 581 | + BinaryToken::Rgb(color) => { |
| 582 | + self.write_header(b"rgb")?; |
| 583 | + self.write_array_start()?; |
| 584 | + self.write_u32(color.r)?; |
| 585 | + self.write_u32(color.g)?; |
| 586 | + self.write_u32(color.b)?; |
| 587 | + self.write_end() |
| 588 | + } |
| 589 | + } |
| 590 | + } |
| 591 | + |
494 | 592 | /// Writes a text tape
|
495 | 593 | ///
|
496 | 594 | /// Formatting is not preserved.
|
|
0 commit comments