Skip to content

Commit a442111

Browse files
authored
Merge pull request #126 from rakaly/writer
Add TextWriter::write_binary and depth
2 parents bebed49 + b0aaf36 commit a442111

File tree

1 file changed

+100
-2
lines changed

1 file changed

+100
-2
lines changed

src/text/writer.rs

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
common::PdsDateFormatter,
33
text::{ArrayReader, ObjectReader, Operator, ValueReader},
4-
Encoding, Error, ErrorKind, TextTape, TextToken,
4+
BinaryToken, Encoding, Error, ErrorKind, TextTape, TextToken,
55
};
66
use std::{fmt::Arguments, io::Write, ops::Deref};
77

@@ -89,8 +89,15 @@ where
8989
}
9090

9191
/// Returns true if the next write event would be a key
92+
#[inline]
9293
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()
94101
}
95102

96103
/// Write out the start of an object
@@ -294,6 +301,23 @@ where
294301
write!(self, "{}", data)
295302
}
296303

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+
297321
/// Write a 32 bit floating point at full precision
298322
///
299323
/// ```
@@ -491,6 +515,80 @@ where
491515
self.mixed_mode = MixedMode::Started;
492516
}
493517

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+
494592
/// Writes a text tape
495593
///
496594
/// Formatting is not preserved.

0 commit comments

Comments
 (0)