Struct jomini::TextWriter

source ·
pub struct TextWriter<W> { /* private fields */ }
Expand description

Write data in PDS format.

Instantiated via TextWriterBuilder

Implementations§

Get inner writer, keeping ownership

Consumes this Writer, returning the underlying writer

Returns true if the next write event would be a key

Write out the start of an object

Examples found in repository?
src/text/writer.rs (line 640)
636
637
638
639
640
641
642
643
644
    fn write_object<R>(&mut self, object: ObjectReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        self.write_object_start()?;
        self.write_object_core(object)?;
        self.write_end()?;
        Ok(())
    }

Write out the start of an array

Examples found in repository?
src/text/writer.rs (line 626)
622
623
624
625
626
627
628
629
630
631
632
633
634
    fn write_array<R>(&mut self, array: ArrayReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        self.write_array_start()?;

        for value in array.values() {
            self.write_value(value)?;
        }

        self.write_end()?;
        Ok(())
    }

Write the end of an array or object

Examples found in repository?
src/text/writer.rs (line 632)
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
    fn write_array<R>(&mut self, array: ArrayReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        self.write_array_start()?;

        for value in array.values() {
            self.write_value(value)?;
        }

        self.write_end()?;
        Ok(())
    }

    fn write_object<R>(&mut self, object: ObjectReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        self.write_object_start()?;
        self.write_object_core(object)?;
        self.write_end()?;
        Ok(())
    }

Write a boolean

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"hello")?;
writer.write_bool(true)?;
writer.write_unquoted(b"foo")?;
writer.write_bool(false)?;
assert_eq!(&out, b"hello=yes\nfoo=no");

Write an non-equal operator

use jomini::{text::Operator, TextWriterBuilder};
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"a")?;
writer.write_operator(Operator::LessThan)?;
writer.write_unquoted(b"b")?;
assert_eq!(&out, b"a < b");
Examples found in repository?
src/text/writer.rs (line 556)
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
    fn write_object_core<R>(&mut self, reader: ObjectReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        for (key, op, value) in reader.fields() {
            match key.token() {
                TextToken::Parameter(x) => {
                    self.write_preamble()?;
                    write!(self.writer, "[[")?;
                    self.writer.write_all(x.as_bytes())?;
                    self.writer.write_all(b"]\n")?;

                    if let Ok(obj) = value.read_object() {
                        self.write_object_core(obj)?;
                        self.writer.write_all(b"\n")?;
                        self.write_indent()?;
                    } else {
                        self.write_value(value)?;
                    }
                    self.writer.write_all(b"]")?;
                }
                TextToken::UndefinedParameter(x) => {
                    self.write_preamble()?;
                    write!(self.writer, "[[!")?;
                    self.writer.write_all(x.as_bytes())?;
                    self.writer.write_all(b"]\n")?;

                    if let Ok(obj) = value.read_object() {
                        self.write_object_core(obj)?;
                        self.writer.write_all(b"\n")?;
                        self.write_indent()?;
                    } else {
                        self.write_value(value)?;
                    }
                    self.writer.write_all(b"]")?;
                }
                TextToken::Quoted(x) => {
                    self.write_escaped_quotes(x.as_bytes())?;
                    if let Some(op) = op {
                        self.write_operator(op)?;
                    }

                    self.write_value(value)?;
                }
                _ => {
                    self.write_unquoted(key.read_scalar().as_bytes())?;
                    if let Some(op) = op {
                        self.write_operator(op)?;
                    }

                    self.write_value(value)?;
                }
            }
        }

        Ok(())
    }

Write bytes directly to the writer.

The contents of the bytes are not checked, so it is up to the caller to ensure that the data is a valid unquoted field (no spaces or control characters).

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"a")?;
writer.write_unquoted(b"b")?;
assert_eq!(&out, b"a=b");
Examples found in repository?
src/text/writer.rs (line 562)
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
    fn write_object_core<R>(&mut self, reader: ObjectReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        for (key, op, value) in reader.fields() {
            match key.token() {
                TextToken::Parameter(x) => {
                    self.write_preamble()?;
                    write!(self.writer, "[[")?;
                    self.writer.write_all(x.as_bytes())?;
                    self.writer.write_all(b"]\n")?;

                    if let Ok(obj) = value.read_object() {
                        self.write_object_core(obj)?;
                        self.writer.write_all(b"\n")?;
                        self.write_indent()?;
                    } else {
                        self.write_value(value)?;
                    }
                    self.writer.write_all(b"]")?;
                }
                TextToken::UndefinedParameter(x) => {
                    self.write_preamble()?;
                    write!(self.writer, "[[!")?;
                    self.writer.write_all(x.as_bytes())?;
                    self.writer.write_all(b"]\n")?;

                    if let Ok(obj) = value.read_object() {
                        self.write_object_core(obj)?;
                        self.writer.write_all(b"\n")?;
                        self.write_indent()?;
                    } else {
                        self.write_value(value)?;
                    }
                    self.writer.write_all(b"]")?;
                }
                TextToken::Quoted(x) => {
                    self.write_escaped_quotes(x.as_bytes())?;
                    if let Some(op) = op {
                        self.write_operator(op)?;
                    }

                    self.write_value(value)?;
                }
                _ => {
                    self.write_unquoted(key.read_scalar().as_bytes())?;
                    if let Some(op) = op {
                        self.write_operator(op)?;
                    }

                    self.write_value(value)?;
                }
            }
        }

        Ok(())
    }

    // For when the data is already escaped
    fn write_escaped_quotes(&mut self, x: &[u8]) -> Result<(), Error> {
        self.write_preamble()?;
        self.writer.write_all(b"\"")?;
        self.writer.write_all(x)?;
        self.writer.write_all(b"\"")?;
        self.write_epilogue()?;
        Ok(())
    }

    fn write_value<R>(&mut self, value: ValueReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        match value.token() {
            TextToken::Array { .. } => self.write_array(value.read_array().unwrap())?,
            TextToken::Object { .. } => self.write_object(value.read_object().unwrap())?,
            TextToken::MixedContainer => self.start_mixed_mode(),
            TextToken::Unquoted(x) => {
                self.write_unquoted(x.as_bytes())?;
            }
            TextToken::Quoted(x) => {
                self.write_escaped_quotes(x.as_bytes())?;
            }
            TextToken::Parameter(_) => unreachable!(),
            TextToken::UndefinedParameter(_) => unreachable!(),
            TextToken::Operator(op) => {
                if self.mixed_mode == MixedMode::Disabled {
                    self.writer.write_all(&b" "[..])?;
                } else {
                    self.mixed_mode = MixedMode::Keyed;
                }
                self.writer.write_all(op.symbol().as_bytes())?;
            }
            TextToken::End(_) => unreachable!(),
            TextToken::Header(x) => {
                let arr = value.read_array().unwrap();
                let mut values = arr.values();
                self.write_header(x.as_bytes())?;
                values.next().unwrap();
                let elem = values.next().unwrap();
                self.write_value(elem)?;
            }
        }
        Ok(())
    }

Write a field to be encapsulated in quotes.

Unlike the unquoted variant, this method will inspect the data to ensure everything is properly escaped, like quotes and escape characters. And will trim trailing newlines. The textual data to write out is assumed to already be in the correct encoding (windows-1252 or UTF-8)

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_quoted(b"name")?;
writer.write_quoted(br#"captain "joe" rogers"#)?;
assert_eq!(&out, b"\"name\"=\"captain \\\"joe\\\" rogers\"");

Write a signed 32bit integer.

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"stability")?;
writer.write_i32(-3);
assert_eq!(&out, b"stability=-3");

Write an unsigned 32bit integer.

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"stability")?;
writer.write_u32(3);
assert_eq!(&out, b"stability=3");

Write an unsigned 64bit integer.

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"seed")?;
writer.write_u64(1000000000000);
assert_eq!(&out, b"seed=1000000000000");

Write a 32 bit floating point at full precision

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"morale")?;
writer.write_f32(4.566);
assert_eq!(&out, b"morale=4.566");

Write a 32 bit floating point at a given precision

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"morale")?;
writer.write_f32_precision(4.0, 3);
assert_eq!(&out, b"morale=4.000");

Write a 64 bit floating point at full precision

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"strength")?;
writer.write_f64(6790.35609);
assert_eq!(&out, b"strength=6790.35609");

Write a 64 bit floating point at a given precision

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"morale")?;
writer.write_f64_precision(4.0, 3);
assert_eq!(&out, b"morale=4.000");

Write a header.

It is undefined if the next commands do not write out the start of an array or object

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"color")?;
writer.write_header(b"rgb")?;
writer.write_array_start()?;
writer.write_i32(100)?;
writer.write_i32(200)?;
writer.write_i32(50)?;
writer.write_end()?;
assert_eq!(&out, b"color=rgb {\n  100 200 50\n}");
Examples found in repository?
src/text/writer.rs (line 613)
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
    fn write_value<R>(&mut self, value: ValueReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        match value.token() {
            TextToken::Array { .. } => self.write_array(value.read_array().unwrap())?,
            TextToken::Object { .. } => self.write_object(value.read_object().unwrap())?,
            TextToken::MixedContainer => self.start_mixed_mode(),
            TextToken::Unquoted(x) => {
                self.write_unquoted(x.as_bytes())?;
            }
            TextToken::Quoted(x) => {
                self.write_escaped_quotes(x.as_bytes())?;
            }
            TextToken::Parameter(_) => unreachable!(),
            TextToken::UndefinedParameter(_) => unreachable!(),
            TextToken::Operator(op) => {
                if self.mixed_mode == MixedMode::Disabled {
                    self.writer.write_all(&b" "[..])?;
                } else {
                    self.mixed_mode = MixedMode::Keyed;
                }
                self.writer.write_all(op.symbol().as_bytes())?;
            }
            TextToken::End(_) => unreachable!(),
            TextToken::Header(x) => {
                let arr = value.read_array().unwrap();
                let mut values = arr.values();
                self.write_header(x.as_bytes())?;
                values.next().unwrap();
                let elem = values.next().unwrap();
                self.write_value(elem)?;
            }
        }
        Ok(())
    }

Write a date formatted in the game style

use jomini::{common::{Date, PdsDate}, TextWriterBuilder};
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
let date = Date::from_ymd(1444, 11, 11);
writer.write_unquoted(b"start")?;
writer.write_date(date.game_fmt())?;
assert_eq!(&out, b"start=1444.11.11");

Write formatted data

Typically not invoked directly but instead through the write! macro

use jomini::TextWriterBuilder;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_unquoted(b"start")?;
write!(writer, "unknown_{}", 5)?;
assert_eq!(&out, b"start=unknown_5");

Enter mixed mode for writing a container that is a list and an object

Examples found in repository?
src/text/writer.rs (line 592)
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
    fn write_value<R>(&mut self, value: ValueReader<R>) -> Result<(), Error>
    where
        R: Encoding + Clone,
    {
        match value.token() {
            TextToken::Array { .. } => self.write_array(value.read_array().unwrap())?,
            TextToken::Object { .. } => self.write_object(value.read_object().unwrap())?,
            TextToken::MixedContainer => self.start_mixed_mode(),
            TextToken::Unquoted(x) => {
                self.write_unquoted(x.as_bytes())?;
            }
            TextToken::Quoted(x) => {
                self.write_escaped_quotes(x.as_bytes())?;
            }
            TextToken::Parameter(_) => unreachable!(),
            TextToken::UndefinedParameter(_) => unreachable!(),
            TextToken::Operator(op) => {
                if self.mixed_mode == MixedMode::Disabled {
                    self.writer.write_all(&b" "[..])?;
                } else {
                    self.mixed_mode = MixedMode::Keyed;
                }
                self.writer.write_all(op.symbol().as_bytes())?;
            }
            TextToken::End(_) => unreachable!(),
            TextToken::Header(x) => {
                let arr = value.read_array().unwrap();
                let mut values = arr.values();
                self.write_header(x.as_bytes())?;
                values.next().unwrap();
                let elem = values.next().unwrap();
                self.write_value(elem)?;
            }
        }
        Ok(())
    }

Writes a text tape

Formatting is not preserved.

use jomini::{TextTape, TextWriterBuilder};
let tape = TextTape::from_slice(b"hello=world")?;
let mut out: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::new().from_writer(&mut out);
writer.write_tape(&tape)?;
assert_eq!(&out, b"hello=world");

Trait Implementations§

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.