1use std::collections::VecDeque;
2
3use crate::macros::{
4 is_alpha, is_ascii, is_blank, is_blankz, is_bom, is_break, is_breakz, is_printable, is_space,
5};
6use crate::{
7 Break, Encoding, Error, Event, EventData, MappingStyle, Result, ScalarStyle, SequenceStyle,
8 TagDirective, VersionDirective, OUTPUT_BUFFER_SIZE,
9};
10
11#[non_exhaustive]
16pub struct Emitter<'w> {
17 pub(crate) write_handler: Option<&'w mut dyn std::io::Write>,
19 pub(crate) buffer: String,
23 pub(crate) raw_buffer: Vec<u8>,
28 pub(crate) encoding: Encoding,
30 pub(crate) canonical: bool,
32 pub(crate) best_indent: i32,
34 pub(crate) best_width: i32,
36 pub(crate) unicode: bool,
38 pub(crate) line_break: Break,
40 pub(crate) states: Vec<EmitterState>,
42 pub(crate) state: EmitterState,
44 pub(crate) events: VecDeque<Event>,
46 pub(crate) indents: Vec<i32>,
48 pub(crate) tag_directives: Vec<TagDirective>,
50 pub(crate) indent: i32,
52 pub(crate) flow_level: i32,
54 pub(crate) root_context: bool,
56 pub(crate) sequence_context: bool,
58 pub(crate) mapping_context: bool,
60 pub(crate) simple_key_context: bool,
62 pub(crate) line: i32,
64 pub(crate) column: i32,
66 pub(crate) whitespace: bool,
68 pub(crate) indention: bool,
70 pub(crate) open_ended: i32,
72 pub(crate) opened: bool,
74 pub(crate) closed: bool,
76 pub(crate) anchors: Vec<Anchors>,
79 pub(crate) last_anchor_id: i32,
81}
82
83impl Default for Emitter<'_> {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
91#[non_exhaustive]
92pub enum EmitterState {
93 #[default]
95 StreamStart = 0,
96 FirstDocumentStart = 1,
98 DocumentStart = 2,
100 DocumentContent = 3,
102 DocumentEnd = 4,
104 FlowSequenceFirstItem = 5,
106 FlowSequenceItem = 6,
108 FlowMappingFirstKey = 7,
110 FlowMappingKey = 8,
112 FlowMappingSimpleValue = 9,
114 FlowMappingValue = 10,
116 BlockSequenceFirstItem = 11,
118 BlockSequenceItem = 12,
120 BlockMappingFirstKey = 13,
122 BlockMappingKey = 14,
124 BlockMappingSimpleValue = 15,
126 BlockMappingValue = 16,
128 End = 17,
130}
131
132#[derive(Copy, Clone, Default)]
133pub(crate) struct Anchors {
134 pub references: i32,
136 pub anchor: i32,
138 pub serialized: bool,
140}
141
142#[derive(Default)]
143struct Analysis<'a> {
144 pub anchor: Option<AnchorAnalysis<'a>>,
145 pub tag: Option<TagAnalysis<'a>>,
146 pub scalar: Option<ScalarAnalysis<'a>>,
147}
148
149struct AnchorAnalysis<'a> {
150 pub anchor: &'a str,
151 pub alias: bool,
152}
153
154struct TagAnalysis<'a> {
155 pub handle: &'a str,
156 pub suffix: &'a str,
157}
158
159struct ScalarAnalysis<'a> {
160 pub value: &'a str,
162 pub multiline: bool,
164 pub flow_plain_allowed: bool,
166 pub block_plain_allowed: bool,
168 pub single_quoted_allowed: bool,
170 pub block_allowed: bool,
172 pub style: ScalarStyle,
174}
175
176impl<'w> Emitter<'w> {
177 pub fn new() -> Emitter<'w> {
179 Emitter {
180 write_handler: None,
181 buffer: String::with_capacity(OUTPUT_BUFFER_SIZE),
182 raw_buffer: Vec::with_capacity(OUTPUT_BUFFER_SIZE),
183 encoding: Encoding::Any,
184 canonical: false,
185 best_indent: 0,
186 best_width: 0,
187 unicode: false,
188 line_break: Break::default(),
189 states: Vec::with_capacity(16),
190 state: EmitterState::default(),
191 events: VecDeque::with_capacity(16),
192 indents: Vec::with_capacity(16),
193 tag_directives: Vec::with_capacity(16),
194 indent: 0,
195 flow_level: 0,
196 root_context: false,
197 sequence_context: false,
198 mapping_context: false,
199 simple_key_context: false,
200 line: 0,
201 column: 0,
202 whitespace: false,
203 indention: false,
204 open_ended: 0,
205 opened: false,
206 closed: false,
207 anchors: Vec::new(),
208 last_anchor_id: 0,
209 }
210 }
211
212 pub fn reset(&mut self) {
214 *self = Self::new();
215 }
216
217 pub fn open(&mut self) -> Result<()> {
222 assert!(!self.opened);
223 let event = Event::stream_start(Encoding::Any);
224 self.emit(event)?;
225 self.opened = true;
226 Ok(())
227 }
228
229 pub fn close(&mut self) -> Result<()> {
234 assert!(self.opened);
235 if self.closed {
236 return Ok(());
237 }
238 let event = Event::stream_end();
239 self.emit(event)?;
240 self.closed = true;
241 Ok(())
242 }
243
244 pub fn set_output_string(&mut self, output: &'w mut Vec<u8>) {
248 assert!(self.write_handler.is_none());
249 if self.encoding == Encoding::Any {
250 self.set_encoding(Encoding::Utf8);
251 } else if self.encoding != Encoding::Utf8 {
252 panic!("cannot output UTF-16 to String")
253 }
254 output.clear();
255 self.write_handler = Some(output);
256 }
257
258 pub fn set_output(&mut self, handler: &'w mut dyn std::io::Write) {
260 assert!(self.write_handler.is_none());
261 self.write_handler = Some(handler);
262 }
263
264 pub fn set_encoding(&mut self, encoding: Encoding) {
266 assert_eq!(self.encoding, Encoding::Any);
267 self.encoding = encoding;
268 }
269
270 pub fn set_canonical(&mut self, canonical: bool) {
273 self.canonical = canonical;
274 }
275
276 pub fn set_indent(&mut self, indent: i32) {
278 self.best_indent = if 1 < indent && indent < 10 { indent } else { 2 };
279 }
280
281 pub fn set_width(&mut self, width: i32) {
283 self.best_width = if width >= 0 { width } else { -1 };
284 }
285
286 pub fn set_unicode(&mut self, unicode: bool) {
288 self.unicode = unicode;
289 }
290
291 pub fn set_break(&mut self, line_break: Break) {
293 self.line_break = line_break;
294 }
295
296 pub fn emit(&mut self, event: Event) -> Result<()> {
303 self.events.push_back(event);
304 while let Some(event) = self.needs_mode_events() {
305 let tag_directives = core::mem::take(&mut self.tag_directives);
306
307 let mut analysis = self.analyze_event(&event, &tag_directives)?;
308 self.state_machine(&event, &mut analysis)?;
309
310 if self.tag_directives.is_empty() {
313 self.tag_directives = tag_directives;
314 }
315 }
316 Ok(())
317 }
318
319 fn flush_if_needed(&mut self) -> Result<()> {
321 if self.buffer.len() < OUTPUT_BUFFER_SIZE - 5 {
322 Ok(())
323 } else {
324 self.flush()
325 }
326 }
327
328 fn put(&mut self, value: char) -> Result<()> {
330 self.flush_if_needed()?;
331 self.buffer.push(value);
332 self.column += 1;
333 Ok(())
334 }
335
336 fn put_break(&mut self) -> Result<()> {
338 self.flush_if_needed()?;
339 if self.line_break == Break::Cr {
340 self.buffer.push('\r');
341 } else if self.line_break == Break::Ln {
342 self.buffer.push('\n');
343 } else if self.line_break == Break::CrLn {
344 self.buffer.push_str("\r\n");
345 }
346 self.column = 0;
347 self.line += 1;
348 Ok(())
349 }
350
351 fn write_str(&mut self, string: &str) -> Result<()> {
355 if self.buffer.len() + string.len() > OUTPUT_BUFFER_SIZE {
356 self.flush()?;
357 }
358
359 self.buffer.reserve(string.len());
362
363 self.column += string.chars().count() as i32;
364
365 self.buffer.push_str(string);
368
369 Ok(())
370 }
371
372 fn write_char(&mut self, ch: char) -> Result<()> {
374 self.flush_if_needed()?;
375 self.buffer.push(ch);
376 self.column += 1;
377 Ok(())
378 }
379
380 fn write_break(&mut self, ch: char) -> Result<()> {
382 self.flush_if_needed()?;
383 if ch == '\n' {
384 self.put_break()?;
385 } else {
386 self.write_char(ch)?;
387 self.column = 0;
388 self.line += 1;
389 }
390 Ok(())
391 }
392
393 fn needs_mode_events(&mut self) -> Option<Event> {
394 let first = self.events.front()?;
395
396 let accummulate = match &first.data {
397 EventData::DocumentStart { .. } => 1,
398 EventData::SequenceStart { .. } => 2,
399 EventData::MappingStart { .. } => 3,
400 _ => return self.events.pop_front(),
401 };
402
403 if self.events.len() > accummulate {
404 return self.events.pop_front();
405 }
406
407 let mut level = 0;
408 for event in &self.events {
409 match event.data {
410 EventData::StreamStart { .. }
411 | EventData::DocumentStart { .. }
412 | EventData::SequenceStart { .. }
413 | EventData::MappingStart { .. } => {
414 level += 1;
415 }
416
417 EventData::StreamEnd
418 | EventData::DocumentEnd { .. }
419 | EventData::SequenceEnd
420 | EventData::MappingEnd => {
421 level -= 1;
422 }
423 _ => {}
424 }
425
426 if level == 0 {
427 return self.events.pop_front();
428 }
429 }
430
431 None
432 }
433
434 fn append_tag_directive(&mut self, value: TagDirective, allow_duplicates: bool) -> Result<()> {
435 for tag_directive in &self.tag_directives {
436 if value.handle == tag_directive.handle {
437 if allow_duplicates {
438 return Ok(());
439 }
440 return Err(Error::emitter("duplicate %TAG directive"));
441 }
442 }
443 self.tag_directives.push(value);
444 Ok(())
445 }
446
447 fn increase_indent(&mut self, flow: bool, indentless: bool) {
448 self.indents.push(self.indent);
449 if self.indent < 0 {
450 self.indent = if flow { self.best_indent } else { 0 };
451 } else if !indentless {
452 self.indent += self.best_indent;
453 }
454 }
455
456 fn state_machine<'a>(&mut self, event: &'a Event, analysis: &mut Analysis<'a>) -> Result<()> {
457 match self.state {
458 EmitterState::StreamStart => self.emit_stream_start(event),
459 EmitterState::FirstDocumentStart => self.emit_document_start(event, true),
460 EmitterState::DocumentStart => self.emit_document_start(event, false),
461 EmitterState::DocumentContent => self.emit_document_content(event, analysis),
462 EmitterState::DocumentEnd => self.emit_document_end(event),
463 EmitterState::FlowSequenceFirstItem => {
464 self.emit_flow_sequence_item(event, true, analysis)
465 }
466 EmitterState::FlowSequenceItem => self.emit_flow_sequence_item(event, false, analysis),
467 EmitterState::FlowMappingFirstKey => self.emit_flow_mapping_key(event, true, analysis),
468 EmitterState::FlowMappingKey => self.emit_flow_mapping_key(event, false, analysis),
469 EmitterState::FlowMappingSimpleValue => {
470 self.emit_flow_mapping_value(event, true, analysis)
471 }
472 EmitterState::FlowMappingValue => self.emit_flow_mapping_value(event, false, analysis),
473 EmitterState::BlockSequenceFirstItem => {
474 self.emit_block_sequence_item(event, true, analysis)
475 }
476 EmitterState::BlockSequenceItem => {
477 self.emit_block_sequence_item(event, false, analysis)
478 }
479 EmitterState::BlockMappingFirstKey => {
480 self.emit_block_mapping_key(event, true, analysis)
481 }
482 EmitterState::BlockMappingKey => self.emit_block_mapping_key(event, false, analysis),
483 EmitterState::BlockMappingSimpleValue => {
484 self.emit_block_mapping_value(event, true, analysis)
485 }
486 EmitterState::BlockMappingValue => {
487 self.emit_block_mapping_value(event, false, analysis)
488 }
489 EmitterState::End => Err(Error::emitter("expected nothing after STREAM-END")),
490 }
491 }
492
493 fn emit_stream_start(&mut self, event: &Event) -> Result<()> {
494 self.open_ended = 0;
495 if let EventData::StreamStart { ref encoding } = event.data {
496 if self.encoding == Encoding::Any {
497 self.encoding = *encoding;
498 }
499 if self.encoding == Encoding::Any {
500 self.encoding = Encoding::Utf8;
501 }
502 if self.best_indent < 2 || self.best_indent > 9 {
503 self.best_indent = 2;
504 }
505 if self.best_width >= 0 && self.best_width <= self.best_indent * 2 {
506 self.best_width = 80;
507 }
508 if self.best_width < 0 {
509 self.best_width = i32::MAX;
510 }
511 if self.line_break == Break::Any {
512 self.line_break = Break::Ln;
513 }
514 self.indent = -1;
515 self.line = 0;
516 self.column = 0;
517 self.whitespace = true;
518 self.indention = true;
519 if self.encoding != Encoding::Utf8 {
520 self.write_bom()?;
521 }
522 self.state = EmitterState::FirstDocumentStart;
523 return Ok(());
524 }
525 Err(Error::emitter("expected STREAM-START"))
526 }
527
528 fn emit_document_start(&mut self, event: &Event, first: bool) -> Result<()> {
529 if let EventData::DocumentStart {
530 version_directive,
531 tag_directives,
532 implicit,
533 } = &event.data
534 {
535 let default_tag_directives: [TagDirective; 2] = [
536 TagDirective {
538 handle: String::from("!"),
539 prefix: String::from("!"),
540 },
541 TagDirective {
542 handle: String::from("!!"),
543 prefix: String::from("tag:yaml.org,2002:"),
544 },
545 ];
546 let mut implicit = *implicit;
547 if let Some(version_directive) = version_directive {
548 Self::analyze_version_directive(*version_directive)?;
549 }
550 for tag_directive in tag_directives {
551 Self::analyze_tag_directive(tag_directive)?;
552 self.append_tag_directive(tag_directive.clone(), false)?;
553 }
554 for tag_directive in default_tag_directives {
555 self.append_tag_directive(tag_directive, true)?;
556 }
557 if !first || self.canonical {
558 implicit = false;
559 }
560 if (version_directive.is_some() || !tag_directives.is_empty()) && self.open_ended != 0 {
561 self.write_indicator("...", true, false, false)?;
562 self.write_indent()?;
563 }
564 self.open_ended = 0;
565 if let Some(version_directive) = version_directive {
566 implicit = false;
567 self.write_indicator("%YAML", true, false, false)?;
568 if version_directive.minor == 1 {
569 self.write_indicator("1.1", true, false, false)?;
570 } else {
571 self.write_indicator("1.2", true, false, false)?;
572 }
573 self.write_indent()?;
574 }
575 if !tag_directives.is_empty() {
576 implicit = false;
577 for tag_directive in tag_directives {
578 self.write_indicator("%TAG", true, false, false)?;
579 self.write_tag_handle(&tag_directive.handle)?;
580 self.write_tag_content(&tag_directive.prefix, true)?;
581 self.write_indent()?;
582 }
583 }
584 if Self::check_empty_document() {
585 implicit = false;
586 }
587 if !implicit {
588 self.write_indent()?;
589 self.write_indicator("---", true, false, false)?;
590 if self.canonical {
591 self.write_indent()?;
592 }
593 }
594 self.state = EmitterState::DocumentContent;
595 self.open_ended = 0;
596 return Ok(());
597 } else if let EventData::StreamEnd = &event.data {
598 if self.open_ended == 2 {
599 self.write_indicator("...", true, false, false)?;
600 self.open_ended = 0;
601 self.write_indent()?;
602 }
603 self.flush()?;
604 self.state = EmitterState::End;
605 return Ok(());
606 }
607
608 Err(Error::emitter("expected DOCUMENT-START or STREAM-END"))
609 }
610
611 fn emit_document_content(&mut self, event: &Event, analysis: &mut Analysis) -> Result<()> {
612 self.states.push(EmitterState::DocumentEnd);
613 self.emit_node(event, true, false, false, false, analysis)
614 }
615
616 fn emit_document_end(&mut self, event: &Event) -> Result<()> {
617 if let EventData::DocumentEnd { implicit } = &event.data {
618 let implicit = *implicit;
619 self.write_indent()?;
620 if !implicit {
621 self.write_indicator("...", true, false, false)?;
622 self.open_ended = 0;
623 self.write_indent()?;
624 } else if self.open_ended == 0 {
625 self.open_ended = 1;
626 }
627 self.flush()?;
628 self.state = EmitterState::DocumentStart;
629 self.tag_directives.clear();
630 return Ok(());
631 }
632
633 Err(Error::emitter("expected DOCUMENT-END"))
634 }
635
636 fn emit_flow_sequence_item(
637 &mut self,
638 event: &Event,
639 first: bool,
640 analysis: &mut Analysis,
641 ) -> Result<()> {
642 if first {
643 self.write_indicator("[", true, true, false)?;
644 self.increase_indent(true, false);
645 self.flow_level += 1;
646 }
647 if let EventData::SequenceEnd = &event.data {
648 self.flow_level -= 1;
649 self.indent = self.indents.pop().unwrap();
650 if self.canonical && !first {
651 self.write_indicator(",", false, false, false)?;
652 self.write_indent()?;
653 }
654 self.write_indicator("]", false, false, false)?;
655 self.state = self.states.pop().unwrap();
656 return Ok(());
657 }
658 if !first {
659 self.write_indicator(",", false, false, false)?;
660 }
661 if self.canonical || self.column > self.best_width {
662 self.write_indent()?;
663 }
664 self.states.push(EmitterState::FlowSequenceItem);
665 self.emit_node(event, false, true, false, false, analysis)
666 }
667
668 fn emit_flow_mapping_key(
669 &mut self,
670 event: &Event,
671 first: bool,
672 analysis: &mut Analysis,
673 ) -> Result<()> {
674 if first {
675 self.write_indicator("{", true, true, false)?;
676 self.increase_indent(true, false);
677 self.flow_level += 1;
678 }
679 if let EventData::MappingEnd = &event.data {
680 assert!(!self.indents.is_empty(), "self.indents should not be empty");
681 self.flow_level -= 1;
682 self.indent = self.indents.pop().unwrap();
683 if self.canonical && !first {
684 self.write_indicator(",", false, false, false)?;
685 self.write_indent()?;
686 }
687 self.write_indicator("}", false, false, false)?;
688 self.state = self.states.pop().unwrap();
689 return Ok(());
690 }
691 if !first {
692 self.write_indicator(",", false, false, false)?;
693 }
694 if self.canonical || self.column > self.best_width {
695 self.write_indent()?;
696 }
697 if !self.canonical && self.check_simple_key(event, analysis) {
698 self.states.push(EmitterState::FlowMappingSimpleValue);
699 self.emit_node(event, false, false, true, true, analysis)
700 } else {
701 self.write_indicator("?", true, false, false)?;
702 self.states.push(EmitterState::FlowMappingValue);
703 self.emit_node(event, false, false, true, false, analysis)
704 }
705 }
706
707 fn emit_flow_mapping_value(
708 &mut self,
709 event: &Event,
710 simple: bool,
711 analysis: &mut Analysis,
712 ) -> Result<()> {
713 if simple {
714 self.write_indicator(":", false, false, false)?;
715 } else {
716 if self.canonical || self.column > self.best_width {
717 self.write_indent()?;
718 }
719 self.write_indicator(":", true, false, false)?;
720 }
721 self.states.push(EmitterState::FlowMappingKey);
722 self.emit_node(event, false, false, true, false, analysis)
723 }
724
725 fn emit_block_sequence_item(
726 &mut self,
727 event: &Event,
728 first: bool,
729 analysis: &mut Analysis,
730 ) -> Result<()> {
731 if first {
732 self.increase_indent(false, self.mapping_context && !self.indention);
733 }
734 if let EventData::SequenceEnd = &event.data {
735 self.indent = self.indents.pop().unwrap();
736 self.state = self.states.pop().unwrap();
737 return Ok(());
738 }
739 self.write_indent()?;
740 self.write_indicator("-", true, false, true)?;
741 self.states.push(EmitterState::BlockSequenceItem);
742 self.emit_node(event, false, true, false, false, analysis)
743 }
744
745 fn emit_block_mapping_key(
746 &mut self,
747 event: &Event,
748 first: bool,
749 analysis: &mut Analysis,
750 ) -> Result<()> {
751 if first {
752 self.increase_indent(false, false);
753 }
754 if let EventData::MappingEnd = &event.data {
755 self.indent = self.indents.pop().unwrap();
756 self.state = self.states.pop().unwrap();
757 return Ok(());
758 }
759 self.write_indent()?;
760 if self.check_simple_key(event, analysis) {
761 self.states.push(EmitterState::BlockMappingSimpleValue);
762 self.emit_node(event, false, false, true, true, analysis)
763 } else {
764 self.write_indicator("?", true, false, true)?;
765 self.states.push(EmitterState::BlockMappingValue);
766 self.emit_node(event, false, false, true, false, analysis)
767 }
768 }
769
770 fn emit_block_mapping_value(
771 &mut self,
772 event: &Event,
773 simple: bool,
774 analysis: &mut Analysis,
775 ) -> Result<()> {
776 if simple {
777 self.write_indicator(":", false, false, false)?;
778 } else {
779 self.write_indent()?;
780 self.write_indicator(":", true, false, true)?;
781 }
782 self.states.push(EmitterState::BlockMappingKey);
783 self.emit_node(event, false, false, true, false, analysis)
784 }
785
786 fn emit_node(
787 &mut self,
788 event: &Event,
789 root: bool,
790 sequence: bool,
791 mapping: bool,
792 simple_key: bool,
793 analysis: &mut Analysis,
794 ) -> Result<()> {
795 self.root_context = root;
796 self.sequence_context = sequence;
797 self.mapping_context = mapping;
798 self.simple_key_context = simple_key;
799
800 match event.data {
801 EventData::Alias { .. } => self.emit_alias(event, analysis.anchor.as_ref()),
802 EventData::Scalar { .. } => self.emit_scalar(event, analysis),
803 EventData::SequenceStart { .. } => self.emit_sequence_start(event, analysis),
804 EventData::MappingStart { .. } => self.emit_mapping_start(event, analysis),
805 _ => Err(Error::emitter(
806 "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS",
807 )),
808 }
809 }
810
811 fn emit_alias(&mut self, _event: &Event, analysis: Option<&AnchorAnalysis>) -> Result<()> {
812 self.process_anchor(analysis)?;
813 if self.simple_key_context {
814 self.put(' ')?;
815 }
816 self.state = self.states.pop().unwrap();
817 Ok(())
818 }
819
820 fn emit_scalar(&mut self, event: &Event, analysis: &mut Analysis) -> Result<()> {
821 let (anchor, tag, scalar) = match analysis {
822 Analysis {
823 anchor,
824 tag,
825 scalar: Some(scalar),
826 } => (anchor, tag, scalar),
827 _ => unreachable!("no scalar analysis"),
828 };
829
830 self.select_scalar_style(event, scalar, tag)?;
831 self.process_anchor(anchor.as_ref())?;
832 self.process_tag(tag.as_ref())?;
833 self.increase_indent(true, false);
834 self.process_scalar(scalar)?;
835 self.indent = self.indents.pop().unwrap();
836 self.state = self.states.pop().unwrap();
837 Ok(())
838 }
839
840 fn emit_sequence_start(&mut self, event: &Event, analysis: &Analysis) -> Result<()> {
841 let Analysis { anchor, tag, .. } = analysis;
842 self.process_anchor(anchor.as_ref())?;
843 self.process_tag(tag.as_ref())?;
844
845 let style = match &event.data {
846 EventData::SequenceStart { style, .. } => style,
847 _ => unreachable!(),
848 };
849
850 if self.flow_level != 0
851 || self.canonical
852 || *style == SequenceStyle::Flow
853 || self.check_empty_sequence(event)
854 {
855 self.state = EmitterState::FlowSequenceFirstItem;
856 } else {
857 self.state = EmitterState::BlockSequenceFirstItem;
858 }
859 Ok(())
860 }
861
862 fn emit_mapping_start(&mut self, event: &Event, analysis: &Analysis) -> Result<()> {
863 let Analysis { anchor, tag, .. } = analysis;
864 self.process_anchor(anchor.as_ref())?;
865 self.process_tag(tag.as_ref())?;
866
867 let style = match &event.data {
868 EventData::MappingStart { style, .. } => style,
869 _ => unreachable!(),
870 };
871
872 if self.flow_level != 0
873 || self.canonical
874 || *style == MappingStyle::Flow
875 || self.check_empty_mapping(event)
876 {
877 self.state = EmitterState::FlowMappingFirstKey;
878 } else {
879 self.state = EmitterState::BlockMappingFirstKey;
880 }
881 Ok(())
882 }
883
884 fn check_empty_document() -> bool {
885 false
886 }
887
888 fn check_empty_sequence(&self, event: &Event) -> bool {
889 if self.events.is_empty() {
890 return false;
891 }
892 let start = matches!(event.data, EventData::SequenceStart { .. });
893 let end = matches!(self.events[0].data, EventData::SequenceEnd);
894 start && end
895 }
896
897 fn check_empty_mapping(&self, event: &Event) -> bool {
898 if self.events.is_empty() {
899 return false;
900 }
901 let start = matches!(event.data, EventData::MappingStart { .. });
902 let end = matches!(self.events[0].data, EventData::MappingEnd);
903 start && end
904 }
905
906 fn check_simple_key(&self, event: &Event, analysis: &Analysis) -> bool {
907 let Analysis {
908 tag,
909 anchor,
910 scalar,
911 } = analysis;
912
913 let mut length = anchor.as_ref().map_or(0, |a| a.anchor.len())
914 + tag.as_ref().map_or(0, |t| t.handle.len() + t.suffix.len());
915
916 match event.data {
917 EventData::Alias { .. } => {
918 length = analysis.anchor.as_ref().map_or(0, |a| a.anchor.len());
919 }
920 EventData::Scalar { .. } => {
921 let scalar = match scalar {
922 Some(scalar) => scalar,
923 None => panic!("no analysis for scalar"),
924 };
925
926 if scalar.multiline {
927 return false;
928 }
929 length += scalar.value.len();
930 }
931 EventData::SequenceStart { .. } => {
932 if !self.check_empty_sequence(event) {
933 return false;
934 }
935 }
936 EventData::MappingStart { .. } => {
937 if !self.check_empty_mapping(event) {
938 return false;
939 }
940 }
941 _ => return false,
942 }
943
944 if length > 128 {
945 return false;
946 }
947
948 true
949 }
950
951 fn select_scalar_style(
952 &mut self,
953 event: &Event,
954 scalar_analysis: &mut ScalarAnalysis,
955 tag_analysis: &mut Option<TagAnalysis>,
956 ) -> Result<()> {
957 let (plain_implicit, quoted_implicit, style) = match &event.data {
958 EventData::Scalar {
959 plain_implicit,
960 quoted_implicit,
961 style,
962 ..
963 } => (plain_implicit, quoted_implicit, style),
964 _ => unreachable!(),
965 };
966
967 let mut style: ScalarStyle = *style;
968 let no_tag = tag_analysis.is_none();
969 if no_tag && !*plain_implicit && !*quoted_implicit {
970 return Err(Error::emitter(
971 "neither tag nor implicit flags are specified",
972 ));
973 }
974 if style == ScalarStyle::Any {
975 style = ScalarStyle::Plain;
976 }
977 if self.canonical {
978 style = ScalarStyle::DoubleQuoted;
979 }
980 if self.simple_key_context && scalar_analysis.multiline {
981 style = ScalarStyle::DoubleQuoted;
982 }
983 if style == ScalarStyle::Plain {
984 if self.flow_level != 0 && !scalar_analysis.flow_plain_allowed
985 || self.flow_level == 0 && !scalar_analysis.block_plain_allowed
986 {
987 style = ScalarStyle::SingleQuoted;
988 }
989 if scalar_analysis.value.is_empty() && (self.flow_level != 0 || self.simple_key_context)
990 {
991 style = ScalarStyle::SingleQuoted;
992 }
993 if no_tag && !*plain_implicit {
994 style = ScalarStyle::SingleQuoted;
995 }
996 }
997 if style == ScalarStyle::SingleQuoted && !scalar_analysis.single_quoted_allowed {
998 style = ScalarStyle::DoubleQuoted;
999 }
1000 if (style == ScalarStyle::Literal || style == ScalarStyle::Folded)
1001 && (!scalar_analysis.block_allowed || self.flow_level != 0 || self.simple_key_context)
1002 {
1003 style = ScalarStyle::DoubleQuoted;
1004 }
1005 if no_tag && !*quoted_implicit && style != ScalarStyle::Plain {
1006 *tag_analysis = Some(TagAnalysis {
1007 handle: "!",
1008 suffix: "",
1009 });
1010 }
1011 scalar_analysis.style = style;
1012 Ok(())
1013 }
1014
1015 fn process_anchor(&mut self, analysis: Option<&AnchorAnalysis>) -> Result<()> {
1016 let analysis = match analysis.as_ref() {
1017 Some(analysis) => analysis,
1018 None => return Ok(()),
1019 };
1020 self.write_indicator(if analysis.alias { "*" } else { "&" }, true, false, false)?;
1021 self.write_anchor(analysis.anchor)
1022 }
1023
1024 fn process_tag(&mut self, analysis: Option<&TagAnalysis>) -> Result<()> {
1025 let analysis = match analysis {
1026 Some(analysis) => analysis,
1027 None => return Ok(()),
1028 };
1029
1030 if analysis.handle.is_empty() && analysis.suffix.is_empty() {
1031 return Ok(());
1032 }
1033 if analysis.handle.is_empty() {
1034 self.write_indicator("!<", true, false, false)?;
1035 self.write_tag_content(analysis.suffix, false)?;
1036 self.write_indicator(">", false, false, false)?;
1037 } else {
1038 self.write_tag_handle(analysis.handle)?;
1039 if !analysis.suffix.is_empty() {
1040 self.write_tag_content(analysis.suffix, false)?;
1041 }
1042 }
1043 Ok(())
1044 }
1045
1046 fn process_scalar(&mut self, analysis: &ScalarAnalysis) -> Result<()> {
1047 match analysis.style {
1048 ScalarStyle::Plain => self.write_plain_scalar(analysis.value, !self.simple_key_context),
1049 ScalarStyle::SingleQuoted => {
1050 self.write_single_quoted_scalar(analysis.value, !self.simple_key_context)
1051 }
1052 ScalarStyle::DoubleQuoted => {
1053 self.write_double_quoted_scalar(analysis.value, !self.simple_key_context)
1054 }
1055 ScalarStyle::Literal => self.write_literal_scalar(analysis.value),
1056 ScalarStyle::Folded => self.write_folded_scalar(analysis.value),
1057 ScalarStyle::Any => unreachable!("No scalar style chosen"),
1058 }
1059 }
1060
1061 fn analyze_version_directive(version_directive: VersionDirective) -> Result<()> {
1062 if version_directive.major != 1
1063 || version_directive.minor != 1 && version_directive.minor != 2
1064 {
1065 return Err(Error::emitter("incompatible %YAML directive"));
1066 }
1067 Ok(())
1068 }
1069
1070 fn analyze_tag_directive(tag_directive: &TagDirective) -> Result<()> {
1071 if tag_directive.handle.is_empty() {
1072 return Err(Error::emitter("tag handle must not be empty"));
1073 }
1074 if !tag_directive.handle.starts_with('!') {
1075 return Err(Error::emitter("tag handle must start with '!'"));
1076 }
1077 if !tag_directive.handle.ends_with('!') {
1078 return Err(Error::emitter("tag handle must end with '!'"));
1079 }
1080 if tag_directive.handle.len() > 2 {
1081 let tag_content = &tag_directive.handle[1..tag_directive.handle.len() - 1];
1082 for ch in tag_content.chars() {
1083 if !is_alpha(ch) {
1084 return Err(Error::emitter(
1085 "tag handle must contain alphanumerical characters only",
1086 ));
1087 }
1088 }
1089 }
1090
1091 if tag_directive.prefix.is_empty() {
1092 return Err(Error::emitter("tag prefix must not be empty"));
1093 }
1094
1095 Ok(())
1096 }
1097
1098 fn analyze_anchor(anchor: &str, alias: bool) -> Result<AnchorAnalysis<'_>> {
1099 if anchor.is_empty() {
1100 return Err(Error::emitter(if alias {
1101 "alias value must not be empty"
1102 } else {
1103 "anchor value must not be empty"
1104 }));
1105 }
1106
1107 for ch in anchor.chars() {
1108 if !is_alpha(ch) {
1109 return Err(Error::emitter(if alias {
1110 "alias value must contain alphanumerical characters only"
1111 } else {
1112 "anchor value must contain alphanumerical characters only"
1113 }));
1114 }
1115 }
1116
1117 Ok(AnchorAnalysis { anchor, alias })
1118 }
1119
1120 fn analyze_tag<'a>(
1121 tag: &'a str,
1122 tag_directives: &'a [TagDirective],
1123 ) -> Result<TagAnalysis<'a>> {
1124 if tag.is_empty() {
1125 return Err(Error::emitter("tag value must not be empty"));
1126 }
1127
1128 let mut handle = "";
1129 let mut suffix = tag;
1130
1131 for tag_directive in tag_directives {
1132 let prefix_len = tag_directive.prefix.len();
1133 if prefix_len < tag.len() && tag_directive.prefix == tag[0..prefix_len] {
1134 handle = &tag_directive.handle;
1135 suffix = &tag[prefix_len..];
1136 break;
1137 }
1138 }
1139
1140 Ok(TagAnalysis { handle, suffix })
1141 }
1142
1143 fn analyze_scalar<'a>(&mut self, value: &'a str) -> Result<ScalarAnalysis<'a>> {
1144 let mut block_indicators = false;
1145 let mut flow_indicators = false;
1146 let mut line_breaks = false;
1147 let mut special_characters = false;
1148 let mut leading_space = false;
1149 let mut leading_break = false;
1150 let mut trailing_space = false;
1151 let mut trailing_break = false;
1152 let mut break_space = false;
1153 let mut space_break = false;
1154 let mut preceded_by_whitespace;
1155 let mut previous_space = false;
1156 let mut previous_break = false;
1157
1158 if value.is_empty() {
1159 return Ok(ScalarAnalysis {
1160 value: "",
1161 multiline: false,
1162 flow_plain_allowed: false,
1163 block_plain_allowed: true,
1164 single_quoted_allowed: true,
1165 block_allowed: false,
1166 style: ScalarStyle::Any,
1167 });
1168 }
1169
1170 if value.starts_with("---") || value.starts_with("...") {
1171 block_indicators = true;
1172 flow_indicators = true;
1173 }
1174 preceded_by_whitespace = true;
1175
1176 let mut chars = value.chars();
1177 let mut first = true;
1178
1179 while let Some(ch) = chars.next() {
1180 let next = chars.clone().next();
1181 let followed_by_whitespace = is_blankz(next);
1182 if first {
1183 match ch {
1184 '#' | ',' | '[' | ']' | '{' | '}' | '&' | '*' | '!' | '|' | '>' | '\''
1185 | '"' | '%' | '@' | '`' => {
1186 flow_indicators = true;
1187 block_indicators = true;
1188 }
1189 '?' | ':' => {
1190 flow_indicators = true;
1191 if followed_by_whitespace {
1192 block_indicators = true;
1193 }
1194 }
1195 '-' if followed_by_whitespace => {
1196 flow_indicators = true;
1197 block_indicators = true;
1198 }
1199 _ => {}
1200 }
1201 } else {
1202 match ch {
1203 ',' | '?' | '[' | ']' | '{' | '}' => {
1204 flow_indicators = true;
1205 }
1206 ':' => {
1207 flow_indicators = true;
1208 if followed_by_whitespace {
1209 block_indicators = true;
1210 }
1211 }
1212 '#' if preceded_by_whitespace => {
1213 flow_indicators = true;
1214 block_indicators = true;
1215 }
1216 _ => {}
1217 }
1218 }
1219
1220 if !is_printable(ch) || !is_ascii(ch) && !self.unicode {
1221 special_characters = true;
1222 }
1223 if is_break(ch) {
1224 line_breaks = true;
1225 }
1226
1227 if is_space(ch) {
1228 if first {
1229 leading_space = true;
1230 }
1231 if next.is_none() {
1232 trailing_space = true;
1233 }
1234 if previous_break {
1235 break_space = true;
1236 }
1237 previous_space = true;
1238 previous_break = false;
1239 } else if is_break(ch) {
1240 if first {
1241 leading_break = true;
1242 }
1243 if next.is_none() {
1244 trailing_break = true;
1245 }
1246 if previous_space {
1247 space_break = true;
1248 }
1249 previous_space = false;
1250 previous_break = true;
1251 } else {
1252 previous_space = false;
1253 previous_break = false;
1254 }
1255
1256 preceded_by_whitespace = is_blankz(ch);
1257 first = false;
1258 }
1259
1260 let mut analysis = ScalarAnalysis {
1261 value,
1262 multiline: line_breaks,
1263 flow_plain_allowed: true,
1264 block_plain_allowed: true,
1265 single_quoted_allowed: true,
1266 block_allowed: true,
1267 style: ScalarStyle::Any,
1268 };
1269
1270 analysis.multiline = line_breaks;
1271 analysis.flow_plain_allowed = true;
1272 analysis.block_plain_allowed = true;
1273 analysis.single_quoted_allowed = true;
1274 analysis.block_allowed = true;
1275 if leading_space || leading_break || trailing_space || trailing_break {
1276 analysis.flow_plain_allowed = false;
1277 analysis.block_plain_allowed = false;
1278 }
1279 if trailing_space {
1280 analysis.block_allowed = false;
1281 }
1282 if break_space {
1283 analysis.flow_plain_allowed = false;
1284 analysis.block_plain_allowed = false;
1285 analysis.single_quoted_allowed = false;
1286 }
1287 if space_break || special_characters {
1288 analysis.flow_plain_allowed = false;
1289 analysis.block_plain_allowed = false;
1290 analysis.single_quoted_allowed = false;
1291 analysis.block_allowed = false;
1292 }
1293 if line_breaks {
1294 analysis.flow_plain_allowed = false;
1295 analysis.block_plain_allowed = false;
1296 }
1297 if flow_indicators {
1298 analysis.flow_plain_allowed = false;
1299 }
1300 if block_indicators {
1301 analysis.block_plain_allowed = false;
1302 }
1303 Ok(analysis)
1304 }
1305
1306 fn analyze_event<'a>(
1307 &mut self,
1308 event: &'a Event,
1309 tag_directives: &'a [TagDirective],
1310 ) -> Result<Analysis<'a>> {
1311 let mut analysis = Analysis::default();
1312
1313 match &event.data {
1314 EventData::Alias { anchor } => {
1315 analysis.anchor = Some(Self::analyze_anchor(anchor, true)?);
1316 }
1317 EventData::Scalar {
1318 anchor,
1319 tag,
1320 value,
1321 plain_implicit,
1322 quoted_implicit,
1323 ..
1324 } => {
1325 let (plain_implicit, quoted_implicit) = (*plain_implicit, *quoted_implicit);
1326 if let Some(anchor) = anchor {
1327 analysis.anchor = Some(Self::analyze_anchor(anchor, false)?);
1328 }
1329 if tag.is_some() && (self.canonical || !plain_implicit && !quoted_implicit) {
1330 analysis.tag =
1331 Some(Self::analyze_tag(tag.as_deref().unwrap(), tag_directives)?);
1332 }
1333 analysis.scalar = Some(self.analyze_scalar(value)?);
1334 }
1335 EventData::SequenceStart {
1336 anchor,
1337 tag,
1338 implicit,
1339 ..
1340 }
1341 | EventData::MappingStart {
1342 anchor,
1343 tag,
1344 implicit,
1345 ..
1346 } => {
1347 if let Some(anchor) = anchor {
1348 analysis.anchor = Some(Self::analyze_anchor(anchor, false)?);
1349 }
1350 if tag.is_some() && (self.canonical || !*implicit) {
1351 analysis.tag =
1352 Some(Self::analyze_tag(tag.as_deref().unwrap(), tag_directives)?);
1353 }
1354 }
1355 _ => {}
1356 }
1357
1358 Ok(analysis)
1359 }
1360
1361 fn write_bom(&mut self) -> Result<()> {
1362 self.flush_if_needed()?;
1363 self.buffer.push('\u{feff}');
1364 Ok(())
1365 }
1366
1367 fn write_indent(&mut self) -> Result<()> {
1368 let indent = if self.indent >= 0 { self.indent } else { 0 };
1369 if !self.indention || self.column > indent || self.column == indent && !self.whitespace {
1370 self.put_break()?;
1371 }
1372 while self.column < indent {
1373 self.put(' ')?;
1374 }
1375 self.whitespace = true;
1376 self.indention = true;
1377 Ok(())
1378 }
1379
1380 fn write_indicator(
1381 &mut self,
1382 indicator: &str,
1383 need_whitespace: bool,
1384 is_whitespace: bool,
1385 is_indention: bool,
1386 ) -> Result<()> {
1387 if need_whitespace && !self.whitespace {
1388 self.put(' ')?;
1389 }
1390 self.write_str(indicator)?;
1391 self.whitespace = is_whitespace;
1392 self.indention = self.indention && is_indention;
1393 Ok(())
1394 }
1395
1396 fn write_anchor(&mut self, value: &str) -> Result<()> {
1397 self.write_str(value)?;
1398 self.whitespace = false;
1399 self.indention = false;
1400 Ok(())
1401 }
1402
1403 fn write_tag_handle(&mut self, value: &str) -> Result<()> {
1404 if !self.whitespace {
1405 self.put(' ')?;
1406 }
1407 self.write_str(value)?;
1408 self.whitespace = false;
1409 self.indention = false;
1410 Ok(())
1411 }
1412
1413 fn write_tag_content(&mut self, value: &str, need_whitespace: bool) -> Result<()> {
1414 if need_whitespace && !self.whitespace {
1415 self.put(' ')?;
1416 }
1417
1418 for ch in value.chars() {
1419 if is_alpha(ch) {
1420 self.write_char(ch)?;
1421 continue;
1422 }
1423
1424 match ch {
1425 ';' | '/' | '?' | ':' | '@' | '&' | '=' | '+' | '$' | ',' | '_' | '.' | '~'
1426 | '*' | '\'' | '(' | ')' | '[' | ']' => {
1427 self.write_char(ch)?;
1428 continue;
1429 }
1430 _ => {}
1431 }
1432
1433 let mut encode_buffer = [0u8; 4];
1435 let encoded_char = ch.encode_utf8(&mut encode_buffer);
1436 for value in encoded_char.bytes() {
1437 let upper = char::from_digit(value as u32 >> 4, 16)
1438 .expect("invalid digit")
1439 .to_ascii_uppercase();
1440 let lower = char::from_digit(value as u32 & 0x0F, 16)
1441 .expect("invalid digit")
1442 .to_ascii_uppercase();
1443 self.put('%')?;
1444 self.put(upper)?;
1445 self.put(lower)?;
1446 }
1447 }
1448
1449 self.whitespace = false;
1450 self.indention = false;
1451 Ok(())
1452 }
1453
1454 fn write_plain_scalar(&mut self, value: &str, allow_breaks: bool) -> Result<()> {
1455 let mut spaces = false;
1456 let mut breaks = false;
1457 if !self.whitespace && (!value.is_empty() || self.flow_level != 0) {
1458 self.put(' ')?;
1459 }
1460
1461 let mut chars = value.chars();
1462
1463 while let Some(ch) = chars.next() {
1464 let next = chars.clone().next();
1465 if is_space(ch) {
1466 if allow_breaks && !spaces && self.column > self.best_width && !is_space(next) {
1467 self.write_indent()?;
1468 } else {
1469 self.write_char(ch)?;
1470 }
1471 spaces = true;
1472 } else if is_break(ch) {
1473 if !breaks && ch == '\n' {
1474 self.put_break()?;
1475 }
1476 self.write_break(ch)?;
1477 self.indention = true;
1478 breaks = true;
1479 } else {
1480 if breaks {
1481 self.write_indent()?;
1482 }
1483 self.write_char(ch)?;
1484 self.indention = false;
1485 spaces = false;
1486 breaks = false;
1487 }
1488 }
1489 self.whitespace = false;
1490 self.indention = false;
1491 Ok(())
1492 }
1493
1494 fn write_single_quoted_scalar(&mut self, value: &str, allow_breaks: bool) -> Result<()> {
1495 let mut spaces = false;
1496 let mut breaks = false;
1497 self.write_indicator("'", true, false, false)?;
1498 let mut chars = value.chars();
1499 let mut is_first = true;
1500 while let Some(ch) = chars.next() {
1501 let next = chars.clone().next();
1502 let is_last = next.is_none();
1503
1504 if is_space(ch) {
1505 if allow_breaks
1506 && !spaces
1507 && self.column > self.best_width
1508 && !is_first
1509 && !is_last
1510 && !is_space(next)
1511 {
1512 self.write_indent()?;
1513 } else {
1514 self.write_char(ch)?;
1515 }
1516 spaces = true;
1517 } else if is_break(ch) {
1518 if !breaks && ch == '\n' {
1519 self.put_break()?;
1520 }
1521 self.write_break(ch)?;
1522 self.indention = true;
1523 breaks = true;
1524 } else {
1525 if breaks {
1526 self.write_indent()?;
1527 }
1528 if ch == '\'' {
1529 self.put('\'')?;
1530 }
1531 self.write_char(ch)?;
1532 self.indention = false;
1533 spaces = false;
1534 breaks = false;
1535 }
1536
1537 is_first = false;
1538 }
1539 if breaks {
1540 self.write_indent()?;
1541 }
1542 self.write_indicator("'", false, false, false)?;
1543 self.whitespace = false;
1544 self.indention = false;
1545 Ok(())
1546 }
1547
1548 fn write_double_quoted_scalar(&mut self, value: &str, allow_breaks: bool) -> Result<()> {
1549 let mut spaces = false;
1550 self.write_indicator("\"", true, false, false)?;
1551 let mut chars = value.chars();
1552 let mut first = true;
1553 while let Some(ch) = chars.next() {
1554 if !is_printable(ch)
1555 || !self.unicode && !is_ascii(ch)
1556 || is_bom(ch)
1557 || is_break(ch)
1558 || ch == '"'
1559 || ch == '\\'
1560 {
1561 self.put('\\')?;
1562 match ch {
1563 '\0' => {
1565 self.put('0')?;
1566 }
1567 '\x07' => {
1568 self.put('a')?;
1569 }
1570 '\x08' => {
1571 self.put('b')?;
1572 }
1573 '\x09' => {
1574 self.put('t')?;
1575 }
1576 '\x0A' => {
1577 self.put('n')?;
1578 }
1579 '\x0B' => {
1580 self.put('v')?;
1581 }
1582 '\x0C' => {
1583 self.put('f')?;
1584 }
1585 '\x0D' => {
1586 self.put('r')?;
1587 }
1588 '\x1B' => {
1589 self.put('e')?;
1590 }
1591 '\x22' => {
1592 self.put('"')?;
1593 }
1594 '\x5C' => {
1595 self.put('\\')?;
1596 }
1597 '\u{0085}' => {
1598 self.put('N')?;
1599 }
1600 '\u{00A0}' => {
1601 self.put('_')?;
1602 }
1603 '\u{2028}' => {
1604 self.put('L')?;
1605 }
1606 '\u{2029}' => {
1607 self.put('P')?;
1608 }
1609 _ => {
1610 let (prefix, width) = if ch <= '\u{00ff}' {
1611 ('x', 2)
1612 } else if ch <= '\u{ffff}' {
1613 ('u', 4)
1614 } else {
1615 ('U', 8)
1616 };
1617 self.put(prefix)?;
1618 let mut k = (width - 1) * 4;
1619 let value_0 = ch as u32;
1620 while k >= 0 {
1621 let digit = (value_0 >> k) & 0x0F;
1622 let digit_char = match char::from_digit(digit, 16) {
1623 Some(digit_char) => digit_char,
1624 None => unreachable!("digit out of range"),
1625 };
1626 let digit_char = digit_char.to_ascii_uppercase();
1628 self.put(digit_char)?;
1629 k -= 4;
1630 }
1631 }
1632 }
1633 spaces = false;
1634 } else if is_space(ch) {
1635 if allow_breaks
1636 && !spaces
1637 && self.column > self.best_width
1638 && !first
1639 && chars.clone().next().is_some()
1640 {
1641 self.write_indent()?;
1642 if is_space(chars.clone().next()) {
1643 self.put('\\')?;
1644 }
1645 } else {
1646 self.write_char(ch)?;
1647 }
1648 spaces = true;
1649 } else {
1650 self.write_char(ch)?;
1651 spaces = false;
1652 }
1653
1654 first = false;
1655 }
1656 self.write_indicator("\"", false, false, false)?;
1657 self.whitespace = false;
1658 self.indention = false;
1659 Ok(())
1660 }
1661
1662 fn write_block_scalar_hints(&mut self, string: &str) -> Result<()> {
1663 let mut chomp_hint: Option<&str> = None;
1664
1665 let first = string.chars().next();
1666 if is_space(first) || is_break(first) {
1667 let indent_hint = match char::from_digit(self.best_indent as u32, 10) {
1668 Some(indent_hint) => indent_hint,
1669 None => unreachable!("self.best_indent out of range"),
1670 };
1671 let mut indent_hint_buffer = [0u8; 1];
1672 let indent_hint = indent_hint.encode_utf8(&mut indent_hint_buffer);
1673 self.write_indicator(indent_hint, false, false, false)?;
1674 }
1675 self.open_ended = 0;
1676
1677 if string.is_empty() {
1678 chomp_hint = Some("-");
1679 } else {
1680 let mut chars_rev = string.chars().rev();
1681 let ch = chars_rev.next();
1682 let next = chars_rev.next();
1683
1684 if !is_break(ch) {
1685 chomp_hint = Some("-");
1686 } else if is_breakz(next) {
1687 chomp_hint = Some("+");
1688 self.open_ended = 2;
1689 }
1690 }
1691
1692 if let Some(chomp_hint) = chomp_hint {
1693 self.write_indicator(chomp_hint, false, false, false)?;
1694 }
1695 Ok(())
1696 }
1697
1698 fn write_literal_scalar(&mut self, value: &str) -> Result<()> {
1699 let mut breaks = true;
1700 self.write_indicator("|", true, false, false)?;
1701 self.write_block_scalar_hints(value)?;
1702 self.put_break()?;
1703 self.indention = true;
1704 self.whitespace = true;
1705 let chars = value.chars();
1706 for ch in chars {
1707 if is_break(ch) {
1708 self.write_break(ch)?;
1709 self.indention = true;
1710 breaks = true;
1711 } else {
1712 if breaks {
1713 self.write_indent()?;
1714 }
1715 self.write_char(ch)?;
1716 self.indention = false;
1717 breaks = false;
1718 }
1719 }
1720 Ok(())
1721 }
1722
1723 fn write_folded_scalar(&mut self, value: &str) -> Result<()> {
1724 let mut breaks = true;
1725 let mut leading_spaces = true;
1726 self.write_indicator(">", true, false, false)?;
1727 self.write_block_scalar_hints(value)?;
1728 self.put_break()?;
1729 self.indention = true;
1730 self.whitespace = true;
1731
1732 let mut chars = value.chars();
1733
1734 while let Some(ch) = chars.next() {
1735 if is_break(ch) {
1736 if !breaks && !leading_spaces && ch == '\n' {
1737 let mut skip_breaks = chars.clone();
1738 while is_break(skip_breaks.next()) {}
1739 if !is_blankz(skip_breaks.next()) {
1740 self.put_break()?;
1741 }
1742 }
1743 self.write_break(ch)?;
1744 self.indention = true;
1745 breaks = true;
1746 } else {
1747 if breaks {
1748 self.write_indent()?;
1749 leading_spaces = is_blank(ch);
1750 }
1751 if !breaks
1752 && is_space(ch)
1753 && !is_space(chars.clone().next())
1754 && self.column > self.best_width
1755 {
1756 self.write_indent()?;
1757 } else {
1758 self.write_char(ch)?;
1759 }
1760 self.indention = false;
1761 breaks = false;
1762 }
1763 }
1764 Ok(())
1765 }
1766
1767 pub fn flush(&mut self) -> Result<()> {
1769 assert!((self.write_handler).is_some());
1770 assert_ne!(self.encoding, Encoding::Any);
1771
1772 if self.buffer.is_empty() {
1773 return Ok(());
1774 }
1775
1776 if self.encoding == Encoding::Utf8 {
1777 let to_emit = self.buffer.as_bytes();
1778 self.write_handler
1779 .as_mut()
1780 .expect("non-null writer")
1781 .write_all(to_emit)?;
1782 self.buffer.clear();
1783 return Ok(());
1784 }
1785
1786 let big_endian = match self.encoding {
1787 Encoding::Any | Encoding::Utf8 => {
1788 unreachable!("unhandled encoding")
1789 }
1790 Encoding::Utf16Le => false,
1791 Encoding::Utf16Be => true,
1792 };
1793
1794 for ch in self.buffer.encode_utf16() {
1795 let bytes = if big_endian {
1796 ch.to_be_bytes()
1797 } else {
1798 ch.to_le_bytes()
1799 };
1800 self.raw_buffer.extend(bytes);
1801 }
1802
1803 let to_emit = self.raw_buffer.as_slice();
1804
1805 self.write_handler
1806 .as_mut()
1807 .expect("non-null function pointer")
1808 .write_all(to_emit)?;
1809 self.buffer.clear();
1810 self.raw_buffer.clear();
1811 Ok(())
1812 }
1813
1814 pub(crate) fn reset_anchors(&mut self) {
1815 self.anchors.clear();
1816 self.last_anchor_id = 0;
1817 }
1818
1819 pub(crate) fn anchor_node_sub(&mut self, index: i32) {
1820 self.anchors[index as usize - 1].references += 1;
1821 if self.anchors[index as usize - 1].references == 2 {
1822 self.last_anchor_id += 1;
1823 self.anchors[index as usize - 1].anchor = self.last_anchor_id;
1824 }
1825 }
1826
1827 pub(crate) fn generate_anchor(anchor_id: i32) -> String {
1828 alloc::format!("id{anchor_id:03}")
1829 }
1830}