1use crate::scalar::ScalarValue;
4use std::collections::{BTreeMap, BTreeSet};
5use std::fmt;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum YamlValue {
14 Scalar(ScalarValue),
16 Sequence(Vec<YamlValue>),
18 Mapping(BTreeMap<String, YamlValue>),
20 Set(BTreeSet<String>),
22 OrderedMapping(Vec<(String, YamlValue)>),
24 Pairs(Vec<(String, YamlValue)>),
26}
27
28impl YamlValue {
29 pub fn cast(node: rowan::SyntaxNode<crate::yaml::Lang>) -> Option<Self> {
31 use crate::lex::SyntaxKind;
32 use crate::yaml::{Mapping, Scalar, Sequence, TaggedNode};
33 use rowan::ast::AstNode;
34
35 match node.kind() {
36 SyntaxKind::SCALAR => {
37 Scalar::cast(node)
39 .map(|scalar| YamlValue::Scalar(ScalarValue::from_scalar(&scalar)))
40 }
41 SyntaxKind::SEQUENCE => {
42 if let Some(seq) = Sequence::cast(node) {
43 let items: Vec<YamlValue> = seq.items().filter_map(YamlValue::cast).collect();
44 Some(YamlValue::Sequence(items))
45 } else {
46 None
47 }
48 }
49 SyntaxKind::MAPPING => {
50 if let Some(mapping) = Mapping::cast(node) {
51 let mut map = std::collections::BTreeMap::new();
52 for (key_node, value_node) in mapping.pairs() {
53 let key_str = match crate::yaml::extract_scalar(&key_node) {
59 Some(key_scalar) => key_scalar.as_string(),
60 None => key_node.text().to_string(),
61 };
62
63 if let Some(value_yaml) = YamlValue::cast(value_node) {
65 map.insert(key_str, value_yaml);
66 }
67 }
68 Some(YamlValue::Mapping(map))
69 } else {
70 None
71 }
72 }
73 SyntaxKind::TAGGED_NODE => {
74 TaggedNode::cast(node).and_then(|tagged| {
77 if let Some(set) = tagged.as_set() {
79 let members: BTreeSet<String> = set
80 .members()
81 .filter_map(|v| v.as_scalar().map(|s| s.as_string()))
82 .collect();
83 return Some(YamlValue::Set(members));
84 }
85 if let Some(entries) = tagged.as_ordered_mapping() {
86 let pairs: Vec<(String, YamlValue)> = entries
87 .into_iter()
88 .filter_map(|e| {
89 let key_node = e.key()?;
91 let key_scalar = Scalar::cast(key_node.children().next()?)?;
92 let key = key_scalar.as_string();
93 let val = e
94 .value()
95 .and_then(|v| v.children().next().and_then(YamlValue::cast))?;
96 Some((key, val))
97 })
98 .collect();
99 return Some(YamlValue::OrderedMapping(pairs));
100 }
101 if let Some(entries) = tagged.as_pairs() {
102 let pairs: Vec<(String, YamlValue)> = entries
103 .into_iter()
104 .filter_map(|e| {
105 let key_node = e.key()?;
106 let key_scalar = Scalar::cast(key_node.children().next()?)?;
107 let key = key_scalar.as_string();
108 let val = e
109 .value()
110 .and_then(|v| v.children().next().and_then(YamlValue::cast))?;
111 Some((key, val))
112 })
113 .collect();
114 return Some(YamlValue::Pairs(pairs));
115 }
116 tagged
118 .as_string()
119 .map(|s| YamlValue::Scalar(ScalarValue::string(s)))
120 })
121 }
122 SyntaxKind::VALUE => {
123 node.children().next().and_then(YamlValue::cast)
125 }
126 _ => None,
127 }
128 }
129
130 pub fn scalar(value: impl Into<ScalarValue>) -> Self {
132 YamlValue::Scalar(value.into())
133 }
134
135 pub const fn sequence() -> Self {
137 YamlValue::Sequence(Vec::new())
138 }
139
140 pub const fn from_sequence(items: Vec<YamlValue>) -> Self {
142 YamlValue::Sequence(items)
143 }
144
145 pub const fn mapping() -> Self {
147 YamlValue::Mapping(BTreeMap::new())
148 }
149
150 pub fn parse_raw(yaml_str: &str) -> Self {
153 use std::str::FromStr;
154
155 if let Ok(parsed) = crate::YamlFile::from_str(yaml_str) {
157 if let Some(doc) = parsed.document() {
158 return Self::from_document(&doc);
159 }
160 }
161
162 YamlValue::Scalar(ScalarValue::parse(yaml_str))
164 }
165
166 pub fn from_document(doc: &crate::yaml::Document) -> Self {
168 use rowan::ast::AstNode;
169 doc.syntax()
170 .children()
171 .find_map(Self::cast)
172 .unwrap_or_else(|| YamlValue::Scalar(ScalarValue::string("")))
173 }
174
175 pub const fn from_mapping(map: BTreeMap<String, YamlValue>) -> Self {
177 YamlValue::Mapping(map)
178 }
179
180 pub const fn set() -> Self {
182 YamlValue::Set(BTreeSet::new())
183 }
184
185 pub const fn from_set(set: BTreeSet<String>) -> Self {
187 YamlValue::Set(set)
188 }
189
190 pub const fn ordered_mapping() -> Self {
192 YamlValue::OrderedMapping(Vec::new())
193 }
194
195 pub const fn from_ordered_mapping(pairs: Vec<(String, YamlValue)>) -> Self {
197 YamlValue::OrderedMapping(pairs)
198 }
199
200 pub const fn pairs() -> Self {
202 YamlValue::Pairs(Vec::new())
203 }
204
205 pub const fn from_pairs(pairs: Vec<(String, YamlValue)>) -> Self {
207 YamlValue::Pairs(pairs)
208 }
209
210 #[inline]
214 pub fn is_scalar(&self) -> bool {
215 matches!(self, YamlValue::Scalar(_))
216 }
217
218 #[inline]
222 pub fn is_sequence(&self) -> bool {
223 matches!(self, YamlValue::Sequence(_))
224 }
225
226 #[inline]
230 pub fn is_mapping(&self) -> bool {
231 matches!(self, YamlValue::Mapping(_))
232 }
233
234 #[inline]
236 pub fn is_set(&self) -> bool {
237 matches!(self, YamlValue::Set(_))
238 }
239
240 #[inline]
242 pub fn is_ordered_mapping(&self) -> bool {
243 matches!(self, YamlValue::OrderedMapping(_))
244 }
245
246 #[inline]
248 pub fn is_pairs(&self) -> bool {
249 matches!(self, YamlValue::Pairs(_))
250 }
251
252 pub fn as_scalar(&self) -> Option<&ScalarValue> {
254 match self {
255 YamlValue::Scalar(s) => Some(s),
256 _ => None,
257 }
258 }
259
260 pub fn as_sequence(&self) -> Option<&[YamlValue]> {
262 match self {
263 YamlValue::Sequence(seq) => Some(seq),
264 _ => None,
265 }
266 }
267
268 pub fn as_sequence_mut(&mut self) -> Option<&mut Vec<YamlValue>> {
270 match self {
271 YamlValue::Sequence(seq) => Some(seq),
272 _ => None,
273 }
274 }
275
276 pub fn as_mapping(&self) -> Option<&BTreeMap<String, YamlValue>> {
278 match self {
279 YamlValue::Mapping(map) => Some(map),
280 _ => None,
281 }
282 }
283
284 pub fn as_mapping_mut(&mut self) -> Option<&mut BTreeMap<String, YamlValue>> {
286 match self {
287 YamlValue::Mapping(map) => Some(map),
288 _ => None,
289 }
290 }
291
292 pub fn as_set(&self) -> Option<&BTreeSet<String>> {
294 match self {
295 YamlValue::Set(set) => Some(set),
296 _ => None,
297 }
298 }
299
300 pub fn as_set_mut(&mut self) -> Option<&mut BTreeSet<String>> {
302 match self {
303 YamlValue::Set(set) => Some(set),
304 _ => None,
305 }
306 }
307
308 pub fn as_ordered_mapping(&self) -> Option<&[(String, YamlValue)]> {
310 match self {
311 YamlValue::OrderedMapping(pairs) => Some(pairs),
312 _ => None,
313 }
314 }
315
316 pub fn as_ordered_mapping_mut(&mut self) -> Option<&mut Vec<(String, YamlValue)>> {
318 match self {
319 YamlValue::OrderedMapping(pairs) => Some(pairs),
320 _ => None,
321 }
322 }
323
324 pub fn as_pairs(&self) -> Option<&[(String, YamlValue)]> {
326 match self {
327 YamlValue::Pairs(pairs) => Some(pairs),
328 _ => None,
329 }
330 }
331
332 pub fn as_pairs_mut(&mut self) -> Option<&mut Vec<(String, YamlValue)>> {
334 match self {
335 YamlValue::Pairs(pairs) => Some(pairs),
336 _ => None,
337 }
338 }
339
340 pub fn as_str(&self) -> Option<&str> {
346 match self {
347 YamlValue::Scalar(s) => Some(s.value()),
348 _ => None,
349 }
350 }
351
352 pub fn to_i64(&self) -> Option<i64> {
361 self.as_scalar().and_then(ScalarValue::to_i64)
362 }
363
364 pub fn to_f64(&self) -> Option<f64> {
372 self.as_scalar().and_then(ScalarValue::to_f64)
373 }
374
375 pub fn to_bool(&self) -> Option<bool> {
384 self.as_scalar().and_then(ScalarValue::to_bool)
385 }
386
387 pub fn to_yaml_string(&self, indent: usize) -> String {
389 match self {
390 YamlValue::Scalar(s) => s.to_yaml_string(),
391 YamlValue::Sequence(seq) => {
392 if seq.is_empty() {
393 "[]".to_string()
394 } else {
395 let mut result = String::with_capacity(seq.len() * 20); let indent_str = " ".repeat(indent);
397 for item in seq {
398 result.push_str(&indent_str);
399 result.push_str(" - ");
400 match item {
401 YamlValue::Scalar(s) => result.push_str(&s.to_yaml_string()),
402 _ => {
403 result.push('\n');
404 result.push_str(&item.to_yaml_string(indent + 4));
405 }
406 }
407 result.push('\n');
408 }
409 result.truncate(result.trim_end().len());
410 result
411 }
412 }
413 YamlValue::Mapping(map) => {
414 if map.is_empty() {
415 "{}".to_string()
416 } else {
417 let mut result = String::with_capacity(map.len() * 30); let indent_str = " ".repeat(indent);
419 for (key, value) in map {
420 result.push_str(&indent_str);
421 result.push_str(key);
422 result.push_str(": ");
423 match value {
424 YamlValue::Scalar(s) => result.push_str(&s.to_yaml_string()),
425 _ => {
426 result.push('\n');
427 result.push_str(&value.to_yaml_string(indent + 2));
428 }
429 }
430 result.push('\n');
431 }
432 result.truncate(result.trim_end().len());
433 result
434 }
435 }
436 YamlValue::Set(set) => {
437 if set.is_empty() {
439 "!!set {}".to_string()
440 } else {
441 let mut result = String::from("!!set");
442 result.push('\n');
443 let indent_str = " ".repeat(indent);
444 for item in set {
445 result.push_str(&indent_str);
446 result.push_str(item);
447 result.push_str(": null");
448 result.push('\n');
449 }
450 result.truncate(result.trim_end().len());
451 result
452 }
453 }
454 YamlValue::OrderedMapping(pairs) => Self::render_tagged_pairs("!!omap", pairs, indent),
455 YamlValue::Pairs(pairs) => Self::render_tagged_pairs("!!pairs", pairs, indent),
456 }
457 }
458
459 fn render_tagged_pairs(tag: &str, pairs: &[(String, YamlValue)], indent: usize) -> String {
461 if pairs.is_empty() {
462 return format!("{tag} []");
463 }
464 let mut result = String::from(tag);
465 result.push('\n');
466 let indent_str = " ".repeat(indent);
467 for (key, value) in pairs {
468 result.push_str(&indent_str);
469 result.push_str(" - ");
470 result.push_str(key);
471 result.push_str(": ");
472 match value {
473 YamlValue::Scalar(s) => result.push_str(&s.to_yaml_string()),
474 _ => {
475 result.push('\n');
476 result.push_str(&value.to_yaml_string(indent + 4));
477 }
478 }
479 result.push('\n');
480 }
481 result.truncate(result.trim_end().len());
482 result
483 }
484}
485
486impl fmt::Display for YamlValue {
487 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
488 write!(f, "{}", self.to_yaml_string(0))
489 }
490}
491
492impl From<String> for YamlValue {
494 fn from(value: String) -> Self {
495 YamlValue::Scalar(ScalarValue::from(value))
496 }
497}
498
499impl From<&str> for YamlValue {
500 fn from(value: &str) -> Self {
501 YamlValue::Scalar(ScalarValue::from(value))
502 }
503}
504
505impl From<i32> for YamlValue {
506 fn from(value: i32) -> Self {
507 YamlValue::Scalar(ScalarValue::from(value))
508 }
509}
510
511impl From<i64> for YamlValue {
512 fn from(value: i64) -> Self {
513 YamlValue::Scalar(ScalarValue::from(value))
514 }
515}
516
517impl From<f32> for YamlValue {
518 fn from(value: f32) -> Self {
519 YamlValue::Scalar(ScalarValue::from(value))
520 }
521}
522
523impl From<f64> for YamlValue {
524 fn from(value: f64) -> Self {
525 YamlValue::Scalar(ScalarValue::from(value))
526 }
527}
528
529impl From<bool> for YamlValue {
530 fn from(value: bool) -> Self {
531 YamlValue::Scalar(ScalarValue::from(value))
532 }
533}
534
535impl From<ScalarValue> for YamlValue {
536 fn from(value: ScalarValue) -> Self {
537 YamlValue::Scalar(value)
538 }
539}
540
541impl From<&YamlValue> for YamlValue {
542 fn from(value: &YamlValue) -> Self {
543 value.clone()
544 }
545}
546
547impl<T> From<Vec<T>> for YamlValue
548where
549 T: Into<YamlValue>,
550{
551 fn from(vec: Vec<T>) -> Self {
552 let values: Vec<_> = vec.into_iter().map(Into::into).collect();
553 YamlValue::Sequence(values)
554 }
555}
556
557impl<K, V> From<BTreeMap<K, V>> for YamlValue
558where
559 K: Into<String>,
560 V: Into<YamlValue>,
561{
562 fn from(map: BTreeMap<K, V>) -> Self {
563 YamlValue::Mapping(map.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
564 }
565}
566
567impl<T> From<BTreeSet<T>> for YamlValue
568where
569 T: Into<String>,
570{
571 fn from(set: BTreeSet<T>) -> Self {
572 YamlValue::Set(set.into_iter().map(Into::into).collect())
573 }
574}
575
576#[cfg(test)]
577mod tests {
578 use super::*;
579
580 fn render_as_yaml<T: crate::AsYaml>(v: &T) -> String {
581 let mut builder = rowan::GreenNodeBuilder::new();
582 v.build_content(&mut builder, 0, false);
583 let green = builder.finish();
584 let node = rowan::SyntaxNode::<crate::yaml::Lang>::new_root(green);
585 node.text().to_string()
586 }
587
588 fn scalar_token_kind(v: &YamlValue) -> crate::lex::SyntaxKind {
589 use rowan::ast::AstNode;
590 let mut builder = rowan::GreenNodeBuilder::new();
591 crate::AsYaml::build_content(v, &mut builder, 0, false);
592 let green = builder.finish();
593 let node = rowan::SyntaxNode::<crate::yaml::Lang>::new_root(green);
594 let scalar = crate::yaml::Scalar::cast(node).expect("scalar node");
595 scalar
596 .syntax()
597 .children_with_tokens()
598 .filter_map(|c| c.into_token())
599 .next()
600 .expect("token")
601 .kind()
602 }
603
604 #[test]
605 fn test_scalar_build_content_token_kind() {
606 use crate::lex::SyntaxKind;
607 assert_eq!(
608 scalar_token_kind(&YamlValue::from("hello")),
609 SyntaxKind::STRING
610 );
611 assert_eq!(scalar_token_kind(&YamlValue::from(42)), SyntaxKind::INT);
612 assert_eq!(scalar_token_kind(&YamlValue::from(1.5)), SyntaxKind::FLOAT);
613 assert_eq!(
617 scalar_token_kind(&YamlValue::Scalar(ScalarValue::string("true"))),
618 SyntaxKind::STRING
619 );
620 assert_eq!(
621 scalar_token_kind(&YamlValue::Scalar(ScalarValue::string("false"))),
622 SyntaxKind::STRING
623 );
624 assert_eq!(
625 scalar_token_kind(&YamlValue::Scalar(ScalarValue::string("null"))),
626 SyntaxKind::STRING
627 );
628 assert_eq!(
630 scalar_token_kind(&YamlValue::Scalar(ScalarValue::parse("true"))),
631 SyntaxKind::BOOL
632 );
633 assert_eq!(
634 scalar_token_kind(&YamlValue::Scalar(ScalarValue::parse("null"))),
635 SyntaxKind::NULL
636 );
637 }
638
639 #[test]
640 fn test_scalar_build_content_quotes_like_scalar_value() {
641 for raw in ["null", "true", "42", "a: b", "", "#c", "- x"] {
645 let sv = ScalarValue::string(raw);
646 assert_eq!(
647 render_as_yaml(&YamlValue::Scalar(sv.clone())),
648 render_as_yaml(&sv),
649 "YamlValue::Scalar({raw:?}) must render like the ScalarValue"
650 );
651 }
652 }
653
654 #[test]
655 fn test_as_yaml_build_content_tagged_and_nested() {
656 let omap = YamlValue::from_ordered_mapping(vec![
659 ("a".to_string(), YamlValue::from("1")),
660 ("b".to_string(), YamlValue::from("2")),
661 ]);
662 assert_eq!(render_as_yaml(&omap), "!!omap\n - a: '1'\n - b: '2'\n");
663
664 let pairs = YamlValue::from_pairs(vec![("a".to_string(), YamlValue::from("1"))]);
665 assert_eq!(render_as_yaml(&pairs), "!!pairs\n - a: '1'\n");
666
667 let set = YamlValue::from_set(BTreeSet::from(["a".to_string(), "b".to_string()]));
668 assert_eq!(render_as_yaml(&set), "!!set\n a: null\n b: null\n");
669
670 let mut inner = BTreeMap::new();
675 inner.insert("x".to_string(), YamlValue::from("1"));
676 inner.insert("y".to_string(), YamlValue::from("2"));
677 let mut outer = BTreeMap::new();
678 outer.insert("o".to_string(), YamlValue::Mapping(inner));
679 assert_eq!(render_as_yaml(&outer), "o:\n x: '1'\n y: '2'\n");
680
681 let pairs2 = YamlValue::from_pairs(vec![
684 ("a".to_string(), YamlValue::from("1")),
685 ("b".to_string(), YamlValue::from("2")),
686 ]);
687 assert_eq!(render_as_yaml(&pairs2), "!!pairs\n - a: '1'\n - b: '2'\n");
688
689 let seq = vec![YamlValue::Sequence(vec![YamlValue::from("a")])];
691 assert_eq!(render_as_yaml(&seq), "- - a\n");
692
693 let mut item = BTreeMap::new();
697 item.insert("x".to_string(), YamlValue::from("1"));
698 item.insert("y".to_string(), YamlValue::from("2"));
699 let seq_of_map = vec![YamlValue::Mapping(item)];
700 assert_eq!(render_as_yaml(&seq_of_map), "- x: '1'\n y: '2'\n");
701 }
702
703 #[test]
704 fn test_as_yaml_build_content() {
705 use crate::AsYaml;
706
707 let seq = vec![YamlValue::from("a"), YamlValue::from("b")];
709 assert_eq!(render_as_yaml(&seq), "- a\n- b\n");
710 assert_eq!(render_as_yaml(&seq.as_slice()), "- a\n- b\n");
711
712 let mut m = BTreeMap::new();
714 m.insert("k".to_string(), YamlValue::from("v"));
715 m.insert("j".to_string(), YamlValue::from("w"));
716 assert_eq!(render_as_yaml(&m), "j: w\nk: v\n");
717
718 let empty_seq: Vec<YamlValue> = vec![];
720 assert_eq!(render_as_yaml(&empty_seq), "[]");
721 let empty_map: BTreeMap<String, YamlValue> = BTreeMap::new();
722 assert_eq!(render_as_yaml(&empty_map), "{}");
723
724 let mut m2 = BTreeMap::new();
726 m2.insert(
727 "list".to_string(),
728 YamlValue::Sequence(vec![YamlValue::from("a")]),
729 );
730 assert_eq!(render_as_yaml(&m2), "list:\n - a\n");
731
732 assert_eq!(
734 render_as_yaml(&YamlValue::Sequence(seq.clone())),
735 "- a\n- b\n"
736 );
737 assert_eq!(
738 render_as_yaml(&YamlValue::Mapping(m.clone())),
739 "j: w\nk: v\n"
740 );
741 assert_eq!(render_as_yaml(&YamlValue::from("scalar")), "scalar");
742
743 assert!(!AsYaml::is_inline(&seq));
746 assert!(AsYaml::is_inline(&empty_seq));
747 assert!(!AsYaml::is_inline(&m));
748 assert!(AsYaml::is_inline(&empty_map));
749 assert!(!AsYaml::is_inline(&seq.as_slice()));
750 assert!(AsYaml::is_inline(&empty_seq.as_slice()));
751 assert!(AsYaml::is_inline(&YamlValue::from("x")));
752 assert!(!AsYaml::is_inline(&YamlValue::Sequence(seq)));
753 assert!(AsYaml::is_inline(&YamlValue::sequence()));
754 assert!(!AsYaml::is_inline(&YamlValue::Mapping(m)));
755 assert!(AsYaml::is_inline(&YamlValue::mapping()));
756 }
757
758 #[test]
759 fn test_parse_raw_variants() {
760 assert!(YamlValue::parse_raw("hello").is_scalar());
763
764 let seq = YamlValue::parse_raw("- a\n- b\n");
765 assert_eq!(
766 seq.as_sequence(),
767 Some([YamlValue::from("a"), YamlValue::from("b")].as_slice())
768 );
769
770 let map = YamlValue::parse_raw("k: v\n");
771 assert_eq!(map.as_mapping().map(|m| m.len()), Some(1));
772
773 let set = YamlValue::parse_raw("!!set\n a: ~\n b: ~\n");
774 assert_eq!(
775 set.as_set(),
776 Some(&BTreeSet::from(["a".to_string(), "b".to_string()]))
777 );
778
779 let omap = YamlValue::parse_raw("!!omap\n - a: 1\n - b: 2\n");
780 assert_eq!(
781 omap.as_ordered_mapping(),
782 Some(
783 [
784 ("a".to_string(), YamlValue::from(1)),
785 ("b".to_string(), YamlValue::from(2)),
786 ]
787 .as_slice()
788 )
789 );
790
791 let pairs = YamlValue::parse_raw("!!pairs\n - a: 1\n - a: 2\n");
792 assert_eq!(
793 pairs.as_pairs(),
794 Some(
795 [
796 ("a".to_string(), YamlValue::from(1)),
797 ("a".to_string(), YamlValue::from(2)),
798 ]
799 .as_slice()
800 )
801 );
802 }
803
804 #[test]
805 fn test_display_matches_to_yaml_string() {
806 let map = {
807 let mut m = BTreeMap::new();
808 m.insert("name".to_string(), YamlValue::from("app"));
809 YamlValue::Mapping(m)
810 };
811 assert_eq!(format!("{}", map), map.to_yaml_string(0));
812 assert_eq!(format!("{}", map), "name: app");
813
814 let scalar = YamlValue::from("hello");
815 assert_eq!(format!("{}", scalar), "hello");
816 }
817
818 #[test]
819 fn test_to_yaml_string_nested_indentation() {
820 let mut inner = BTreeMap::new();
823 inner.insert("h".to_string(), YamlValue::from("x"));
824 let seq = YamlValue::Sequence(vec![YamlValue::Mapping(inner)]);
825 assert_eq!(seq.to_yaml_string(0), " - \n h: x");
826
827 let mut m = BTreeMap::new();
830 m.insert(
831 "k".to_string(),
832 YamlValue::Sequence(vec![YamlValue::from("a")]),
833 );
834 assert_eq!(YamlValue::Mapping(m).to_yaml_string(0), "k: \n - a");
835
836 let mut inner2 = BTreeMap::new();
838 inner2.insert("x".to_string(), YamlValue::from("y"));
839 let omap =
840 YamlValue::from_ordered_mapping(vec![("a".to_string(), YamlValue::Mapping(inner2))]);
841 assert_eq!(omap.to_yaml_string(0), "!!omap\n - a: \n x: y");
842
843 let pairs = YamlValue::from_pairs(vec![(
845 "a".to_string(),
846 YamlValue::Sequence(vec![YamlValue::from("z")]),
847 )]);
848 assert_eq!(pairs.to_yaml_string(0), "!!pairs\n - a: \n - z");
849 }
850
851 #[test]
852 fn test_scalar_value() {
853 let val = YamlValue::from("hello");
854 assert!(val.is_scalar());
855 assert_eq!(val.to_yaml_string(0), "hello");
856
857 let val = YamlValue::from(42);
858 assert!(val.is_scalar());
859 assert_eq!(val.to_yaml_string(0), "42");
860
861 let val = YamlValue::from(true);
862 assert!(val.is_scalar());
863 assert_eq!(val.to_yaml_string(0), "true");
864 }
865
866 #[test]
867 fn test_sequence_value() {
868 let val = YamlValue::from(vec!["item1", "item2", "item3"]);
869 assert!(val.is_sequence());
870 let yaml = val.to_yaml_string(0);
871 assert_eq!(yaml, " - item1\n - item2\n - item3");
872
873 let val = YamlValue::sequence();
875 assert_eq!(val.to_yaml_string(0), "[]");
876 }
877
878 #[test]
879 fn test_mapping_value() {
880 let mut map = BTreeMap::new();
881 map.insert("name", YamlValue::from("project"));
882 map.insert("version", YamlValue::from("1.0.0"));
883
884 let val = YamlValue::from(map);
885 assert!(val.is_mapping());
886 let yaml = val.to_yaml_string(0);
887 assert_eq!(yaml, "name: project\nversion: 1.0.0");
888
889 let val = YamlValue::mapping();
891 assert_eq!(val.to_yaml_string(0), "{}");
892 }
893
894 #[test]
895 fn test_nested_structure() {
896 let mut db_map = BTreeMap::new();
897 db_map.insert("host", YamlValue::from("localhost"));
898 db_map.insert("port", YamlValue::from(5432));
899
900 let mut root_map = BTreeMap::new();
901 root_map.insert("name", YamlValue::from("app"));
902 root_map.insert("database", YamlValue::from(db_map));
903 root_map.insert("features", YamlValue::from(vec!["auth", "logging"]));
904
905 let val = YamlValue::from(root_map);
906 let yaml = val.to_yaml_string(0);
907 assert_eq!(
908 yaml,
909 "database: \n host: localhost\n port: 5432\nfeatures: \n - auth\n - logging\nname: app"
910 );
911 }
912
913 #[test]
914 fn test_set_value() {
915 let mut set = BTreeSet::new();
916 set.insert("item1".to_string());
917 set.insert("item2".to_string());
918 set.insert("item3".to_string());
919
920 let val = YamlValue::from_set(set);
921 assert!(val.is_set());
922 let yaml = val.to_yaml_string(0);
923 assert_eq!(yaml, "!!set\nitem1: null\nitem2: null\nitem3: null");
924
925 let val = YamlValue::set();
927 assert_eq!(val.to_yaml_string(0), "!!set {}");
928 }
929
930 #[test]
931 fn test_ordered_mapping_value() {
932 let pairs = vec![
933 ("first".to_string(), YamlValue::from("value1")),
934 ("second".to_string(), YamlValue::from("value2")),
935 ("third".to_string(), YamlValue::from("value3")),
936 ];
937
938 let val = YamlValue::from_ordered_mapping(pairs);
939 assert!(val.is_ordered_mapping());
940 let yaml = val.to_yaml_string(0);
941 assert_eq!(
942 yaml,
943 "!!omap\n - first: value1\n - second: value2\n - third: value3"
944 );
945
946 let val = YamlValue::ordered_mapping();
948 assert_eq!(val.to_yaml_string(0), "!!omap []");
949 }
950
951 #[test]
952 fn test_pairs_value() {
953 let pairs = vec![
954 ("key1".to_string(), YamlValue::from("value1")),
955 ("key1".to_string(), YamlValue::from("value2")), ("key2".to_string(), YamlValue::from("value3")),
957 ];
958
959 let val = YamlValue::from_pairs(pairs);
960 assert!(val.is_pairs());
961 let yaml = val.to_yaml_string(0);
962 assert_eq!(
963 yaml,
964 "!!pairs\n - key1: value1\n - key1: value2\n - key2: value3"
965 );
966
967 let val = YamlValue::pairs();
969 assert_eq!(val.to_yaml_string(0), "!!pairs []");
970 }
971
972 #[test]
973 fn test_predicates_and_accessors() {
974 let scalar = YamlValue::from("s");
975 let seq = YamlValue::Sequence(vec![YamlValue::from("a")]);
976 let map = {
977 let mut m = BTreeMap::new();
978 m.insert("k".to_string(), YamlValue::from("v"));
979 YamlValue::Mapping(m)
980 };
981 let set = YamlValue::from_set(BTreeSet::from(["x".to_string()]));
982 let omap = YamlValue::from_ordered_mapping(vec![("a".to_string(), YamlValue::from("b"))]);
983 let pairs = YamlValue::from_pairs(vec![("a".to_string(), YamlValue::from("b"))]);
984
985 assert!(scalar.is_scalar());
987 assert!(!seq.is_scalar());
988
989 assert!(seq.is_sequence());
990 assert!(!scalar.is_sequence());
991
992 assert!(map.is_mapping());
993 assert!(!seq.is_mapping());
994
995 assert!(set.is_set());
996 assert!(!map.is_set());
997
998 assert!(omap.is_ordered_mapping());
999 assert!(!map.is_ordered_mapping());
1000
1001 assert!(pairs.is_pairs());
1002 assert!(!omap.is_pairs());
1003
1004 assert!(scalar.as_scalar().is_some());
1006 assert!(seq.as_scalar().is_none());
1007
1008 assert_eq!(seq.as_sequence(), Some([YamlValue::from("a")].as_slice()));
1009 assert_eq!(scalar.as_sequence(), None);
1010
1011 assert_eq!(map.as_mapping().map(|m| m.len()), Some(1));
1012 assert_eq!(scalar.as_mapping(), None);
1013
1014 assert_eq!(set.as_set().map(|s| s.len()), Some(1));
1015 assert_eq!(map.as_set(), None);
1016
1017 assert_eq!(omap.as_ordered_mapping().map(|p| p.len()), Some(1));
1018 assert_eq!(map.as_ordered_mapping(), None);
1019
1020 assert_eq!(pairs.as_pairs().map(|p| p.len()), Some(1));
1021 assert_eq!(omap.as_pairs(), None);
1022 }
1023
1024 #[test]
1025 fn test_accessors_mut() {
1026 let mut seq = YamlValue::Sequence(vec![YamlValue::from("a")]);
1027 seq.as_sequence_mut().unwrap().push(YamlValue::from("b"));
1028 assert_eq!(seq.as_sequence().map(|s| s.len()), Some(2));
1029 assert!(YamlValue::from("x").as_sequence_mut().is_none());
1030
1031 let mut map = YamlValue::mapping();
1032 map.as_mapping_mut()
1033 .unwrap()
1034 .insert("k".to_string(), YamlValue::from("v"));
1035 assert_eq!(map.as_mapping().map(|m| m.len()), Some(1));
1036 assert!(YamlValue::from("x").as_mapping_mut().is_none());
1037
1038 let mut set = YamlValue::set();
1039 set.as_set_mut().unwrap().insert("a".to_string());
1040 assert_eq!(set.as_set().map(|s| s.len()), Some(1));
1041 assert!(YamlValue::from("x").as_set_mut().is_none());
1042
1043 let mut omap = YamlValue::ordered_mapping();
1044 omap.as_ordered_mapping_mut()
1045 .unwrap()
1046 .push(("a".to_string(), YamlValue::from("b")));
1047 assert_eq!(omap.as_ordered_mapping().map(|p| p.len()), Some(1));
1048 assert!(YamlValue::from("x").as_ordered_mapping_mut().is_none());
1049
1050 let mut pairs = YamlValue::pairs();
1051 pairs
1052 .as_pairs_mut()
1053 .unwrap()
1054 .push(("a".to_string(), YamlValue::from("b")));
1055 assert_eq!(pairs.as_pairs().map(|p| p.len()), Some(1));
1056 assert!(YamlValue::from("x").as_pairs_mut().is_none());
1057 }
1058
1059 #[test]
1060 fn test_as_str() {
1061 let string_val = YamlValue::from("hello");
1063 assert_eq!(string_val.as_str(), Some("hello"));
1064
1065 let int_val = YamlValue::from(42);
1066 assert_eq!(int_val.as_str(), Some("42"));
1067
1068 let float_val = YamlValue::from(1.5);
1069 assert_eq!(float_val.as_str(), Some("1.5"));
1070
1071 let bool_val = YamlValue::from(true);
1072 assert_eq!(bool_val.as_str(), Some("true"));
1073
1074 let mapping = YamlValue::mapping();
1076 assert_eq!(mapping.as_str(), None);
1077
1078 let sequence = YamlValue::sequence();
1079 assert_eq!(sequence.as_str(), None);
1080
1081 let set = YamlValue::set();
1082 assert_eq!(set.as_str(), None);
1083 }
1084
1085 #[test]
1086 fn test_to_i64() {
1087 use crate::scalar::ScalarValue;
1088
1089 let int_val = YamlValue::Scalar(ScalarValue::parse("42"));
1091 assert_eq!(int_val.to_i64(), Some(42));
1092
1093 let neg_int = YamlValue::Scalar(ScalarValue::parse("-123"));
1094 assert_eq!(neg_int.to_i64(), Some(-123));
1095
1096 let hex_val = YamlValue::Scalar(ScalarValue::parse("0x2A"));
1098 assert_eq!(hex_val.to_i64(), Some(42));
1099
1100 let bin_val = YamlValue::Scalar(ScalarValue::parse("0b101010"));
1102 assert_eq!(bin_val.to_i64(), Some(42));
1103
1104 let oct_val = YamlValue::Scalar(ScalarValue::parse("0o52"));
1106 assert_eq!(oct_val.to_i64(), Some(42));
1107
1108 let string_val = YamlValue::from("42");
1110 assert_eq!(string_val.to_i64(), None);
1111
1112 let bool_val = YamlValue::Scalar(ScalarValue::parse("true"));
1114 assert_eq!(bool_val.to_i64(), None);
1115
1116 let no_val = YamlValue::Scalar(ScalarValue::parse("no"));
1117 assert_eq!(no_val.to_i64(), None);
1118
1119 let float_val = YamlValue::Scalar(ScalarValue::parse("3.14"));
1121 assert_eq!(float_val.to_i64(), None);
1122
1123 let mapping = YamlValue::mapping();
1125 assert_eq!(mapping.to_i64(), None);
1126
1127 let sequence = YamlValue::sequence();
1128 assert_eq!(sequence.to_i64(), None);
1129
1130 let random_string = YamlValue::from("blah");
1132 assert_eq!(random_string.to_i64(), None);
1133
1134 let large_int = YamlValue::Scalar(ScalarValue::parse("23432"));
1136 assert_eq!(large_int.to_i64(), Some(23432));
1137
1138 let zero = YamlValue::Scalar(ScalarValue::parse("0"));
1140 assert_eq!(zero.to_i64(), Some(0));
1141
1142 let one = YamlValue::Scalar(ScalarValue::parse("1"));
1143 assert_eq!(one.to_i64(), Some(1));
1144
1145 let quoted_one = YamlValue::from("1");
1147 assert_eq!(quoted_one.to_i64(), None);
1148
1149 let quoted_zero = YamlValue::from("0");
1150 assert_eq!(quoted_zero.to_i64(), None);
1151 }
1152
1153 #[test]
1154 fn test_to_f64() {
1155 use crate::scalar::ScalarValue;
1156
1157 let float_val = YamlValue::Scalar(ScalarValue::parse("1.5"));
1159 assert_eq!(float_val.to_f64(), Some(1.5));
1160
1161 let neg_float = YamlValue::Scalar(ScalarValue::parse("-2.5"));
1162 assert_eq!(neg_float.to_f64(), Some(-2.5));
1163
1164 let sci_val = YamlValue::Scalar(ScalarValue::parse("1.23e10"));
1166 assert_eq!(sci_val.to_f64(), Some(1.23e10));
1167
1168 let string_val = YamlValue::from("3.14");
1170 assert_eq!(string_val.to_f64(), None);
1171
1172 let int_val = YamlValue::Scalar(ScalarValue::parse("42"));
1174 assert_eq!(int_val.to_f64(), None);
1175
1176 let bool_val = YamlValue::Scalar(ScalarValue::parse("true"));
1178 assert_eq!(bool_val.to_f64(), None);
1179
1180 let mapping = YamlValue::mapping();
1182 assert_eq!(mapping.to_f64(), None);
1183
1184 let sequence = YamlValue::sequence();
1185 assert_eq!(sequence.to_f64(), None);
1186
1187 let random_string = YamlValue::from("blah");
1189 assert_eq!(random_string.to_f64(), None);
1190 }
1191
1192 #[test]
1193 fn test_to_bool() {
1194 use crate::scalar::ScalarValue;
1195
1196 let true_val = YamlValue::Scalar(ScalarValue::parse("true"));
1198 assert_eq!(true_val.to_bool(), Some(true));
1199
1200 let false_val = YamlValue::Scalar(ScalarValue::parse("false"));
1201 assert_eq!(false_val.to_bool(), Some(false));
1202
1203 let yes_val = YamlValue::Scalar(ScalarValue::parse("yes"));
1204 assert_eq!(yes_val.to_bool(), Some(true));
1205
1206 let no_val = YamlValue::Scalar(ScalarValue::parse("no"));
1207 assert_eq!(no_val.to_bool(), Some(false));
1208
1209 let on_val = YamlValue::Scalar(ScalarValue::parse("on"));
1210 assert_eq!(on_val.to_bool(), Some(true));
1211
1212 let off_val = YamlValue::Scalar(ScalarValue::parse("off"));
1213 assert_eq!(off_val.to_bool(), Some(false));
1214
1215 let true_upper = YamlValue::Scalar(ScalarValue::parse("TRUE"));
1217 assert_eq!(true_upper.to_bool(), Some(true));
1218
1219 let yes_mixed = YamlValue::Scalar(ScalarValue::parse("Yes"));
1220 assert_eq!(yes_mixed.to_bool(), Some(true));
1221
1222 let quoted_true = YamlValue::from("true");
1224 assert_eq!(quoted_true.to_bool(), None);
1225
1226 let quoted_false = YamlValue::from("false");
1227 assert_eq!(quoted_false.to_bool(), None);
1228
1229 let quoted_yes = YamlValue::from("yes");
1230 assert_eq!(quoted_yes.to_bool(), None);
1231
1232 let quoted_no = YamlValue::from("no");
1233 assert_eq!(quoted_no.to_bool(), None);
1234
1235 let zero = YamlValue::Scalar(ScalarValue::parse("0"));
1237 assert_eq!(zero.to_bool(), None);
1238
1239 let one = YamlValue::Scalar(ScalarValue::parse("1"));
1240 assert_eq!(one.to_bool(), None);
1241
1242 let large_int = YamlValue::Scalar(ScalarValue::parse("23432"));
1243 assert_eq!(large_int.to_bool(), None);
1244
1245 let quoted_one = YamlValue::from("1");
1247 assert_eq!(quoted_one.to_bool(), None);
1248
1249 let quoted_zero = YamlValue::from("0");
1250 assert_eq!(quoted_zero.to_bool(), None);
1251
1252 let random_string = YamlValue::from("blah");
1254 assert_eq!(random_string.to_bool(), None);
1255
1256 let mapping = YamlValue::mapping();
1258 assert_eq!(mapping.to_bool(), None);
1259
1260 let sequence = YamlValue::sequence();
1261 assert_eq!(sequence.to_bool(), None);
1262
1263 let float_val = YamlValue::Scalar(ScalarValue::parse("3.14"));
1265 assert_eq!(float_val.to_bool(), None);
1266 }
1267}
1268
1269use crate::as_yaml::{AsYaml, YamlKind};
1271use crate::yaml::SyntaxNode;
1272
1273fn build_tagged_pair_seq(
1276 builder: &mut rowan::GreenNodeBuilder,
1277 tag: &str,
1278 pairs: &[(String, YamlValue)],
1279 indent: usize,
1280) -> bool {
1281 use crate::lex::SyntaxKind;
1282
1283 builder.start_node(SyntaxKind::TAGGED_NODE.into());
1284 builder.token(SyntaxKind::TAG.into(), tag);
1285 builder.token(SyntaxKind::NEWLINE.into(), "\n");
1286 builder.token(SyntaxKind::INDENT.into(), &" ".repeat(indent + 2));
1287
1288 let seq: Vec<YamlValue> = pairs
1289 .iter()
1290 .map(|(k, v)| {
1291 let mut map = BTreeMap::new();
1292 map.insert(k.clone(), v.clone());
1293 YamlValue::Mapping(map)
1294 })
1295 .collect();
1296 let ends_with_newline = seq.as_slice().build_content(builder, indent + 2, false);
1297
1298 builder.finish_node(); ends_with_newline
1300}
1301
1302impl AsYaml for YamlValue {
1303 fn as_node(&self) -> Option<&SyntaxNode> {
1304 None
1305 }
1306
1307 fn kind(&self) -> YamlKind {
1308 match self {
1309 YamlValue::Scalar(_) => YamlKind::Scalar,
1310 YamlValue::Sequence(_) => YamlKind::Sequence,
1311 YamlValue::Mapping(_) => YamlKind::Mapping,
1312 YamlValue::Set(_) => YamlKind::Tagged(std::borrow::Cow::Borrowed("!!set")),
1313 YamlValue::OrderedMapping(_) => YamlKind::Tagged(std::borrow::Cow::Borrowed("!!omap")),
1314 YamlValue::Pairs(_) => YamlKind::Tagged(std::borrow::Cow::Borrowed("!!pairs")),
1315 }
1316 }
1317
1318 fn build_content(
1319 &self,
1320 builder: &mut rowan::GreenNodeBuilder,
1321 indent: usize,
1322 flow_context: bool,
1323 ) -> bool {
1324 use crate::lex::SyntaxKind;
1325 match self {
1326 YamlValue::Scalar(s) => s.build_content(builder, indent, flow_context),
1327 YamlValue::Mapping(map) => map.build_content(builder, indent, flow_context),
1328 YamlValue::Sequence(seq) => seq.as_slice().build_content(builder, indent, flow_context),
1329 YamlValue::Set(set) => {
1330 if set.is_empty() {
1331 builder.start_node(SyntaxKind::TAGGED_NODE.into());
1333 builder.token(SyntaxKind::TAG.into(), "!!set");
1334 builder.token(SyntaxKind::WHITESPACE.into(), " ");
1335 builder.start_node(SyntaxKind::MAPPING.into());
1336 builder.token(SyntaxKind::LEFT_BRACE.into(), "{");
1337 builder.token(SyntaxKind::RIGHT_BRACE.into(), "}");
1338 builder.finish_node(); builder.finish_node(); return false;
1341 }
1342
1343 builder.start_node(SyntaxKind::TAGGED_NODE.into());
1345 builder.token(SyntaxKind::TAG.into(), "!!set");
1346 builder.token(SyntaxKind::NEWLINE.into(), "\n");
1347 builder.token(SyntaxKind::INDENT.into(), &" ".repeat(indent + 2));
1348
1349 let map: BTreeMap<String, YamlValue> = set
1351 .iter()
1352 .map(|k| (k.clone(), YamlValue::Scalar(ScalarValue::null())))
1353 .collect();
1354 let ends_with_newline = map.build_content(builder, indent + 2, false);
1355
1356 builder.finish_node(); ends_with_newline
1359 }
1360 YamlValue::OrderedMapping(pairs) => {
1361 build_tagged_pair_seq(builder, "!!omap", pairs, indent)
1362 }
1363 YamlValue::Pairs(pairs) => build_tagged_pair_seq(builder, "!!pairs", pairs, indent),
1364 }
1365 }
1366
1367 fn is_inline(&self) -> bool {
1368 match self {
1369 YamlValue::Scalar(_) => true,
1370 YamlValue::Mapping(map) => map.is_empty(),
1371 YamlValue::Sequence(seq) => seq.is_empty(),
1372 YamlValue::Set(_) => true,
1377 YamlValue::OrderedMapping(_) => true,
1378 YamlValue::Pairs(_) => true,
1379 }
1380 }
1381}
1382
1383#[derive(Debug, Clone, Copy)]
1384enum CollectionStyle {
1385 Flow,
1386 Block,
1387}
1388
1389impl AsYaml for BTreeMap<String, YamlValue> {
1390 fn as_node(&self) -> Option<&SyntaxNode> {
1391 None
1392 }
1393
1394 fn kind(&self) -> YamlKind {
1395 YamlKind::Mapping
1396 }
1397
1398 fn build_content(
1399 &self,
1400 builder: &mut rowan::GreenNodeBuilder,
1401 indent: usize,
1402 _flow_context: bool,
1403 ) -> bool {
1404 use crate::lex::SyntaxKind;
1405
1406 let style = if self.is_empty() {
1407 CollectionStyle::Flow
1408 } else {
1409 CollectionStyle::Block
1410 };
1411
1412 builder.start_node(SyntaxKind::MAPPING.into());
1413
1414 match style {
1415 CollectionStyle::Flow => {
1416 builder.token(SyntaxKind::LEFT_BRACE.into(), "{");
1417 builder.token(SyntaxKind::RIGHT_BRACE.into(), "}");
1418 }
1419 CollectionStyle::Block => {
1420 let indent_str = " ".repeat(indent);
1421 let entries: Vec<_> = self.iter().collect();
1422
1423 for (i, (key, value)) in entries.iter().enumerate() {
1424 if i > 0 {
1425 builder.token(SyntaxKind::INDENT.into(), &indent_str);
1427 }
1428
1429 builder.start_node(SyntaxKind::MAPPING_ENTRY.into());
1430
1431 builder.start_node(SyntaxKind::KEY.into());
1432 key.as_str().build_content(builder, 0, false);
1433 builder.finish_node(); builder.token(SyntaxKind::COLON.into(), ":");
1436
1437 builder.start_node(SyntaxKind::VALUE.into());
1438
1439 let is_complex =
1440 value.kind() == YamlKind::Mapping || value.kind() == YamlKind::Sequence;
1441
1442 let value_ends_with_newline = if is_complex {
1443 builder.token(SyntaxKind::NEWLINE.into(), "\n");
1444 builder.token(SyntaxKind::INDENT.into(), &" ".repeat(indent + 2));
1445 value.build_content(builder, indent + 2, _flow_context)
1446 } else {
1447 builder.token(SyntaxKind::WHITESPACE.into(), " ");
1448 value.build_content(builder, 0, _flow_context)
1449 };
1450
1451 builder.finish_node(); if !value_ends_with_newline {
1456 builder.token(SyntaxKind::NEWLINE.into(), "\n");
1457 }
1458
1459 builder.finish_node(); }
1461 }
1462 }
1463
1464 builder.finish_node(); matches!(style, CollectionStyle::Block) && !self.is_empty()
1467 }
1468
1469 fn is_inline(&self) -> bool {
1470 self.is_empty()
1471 }
1472}
1473
1474impl AsYaml for Vec<YamlValue> {
1475 fn as_node(&self) -> Option<&SyntaxNode> {
1476 None
1477 }
1478
1479 fn kind(&self) -> YamlKind {
1480 YamlKind::Sequence
1481 }
1482
1483 fn build_content(
1484 &self,
1485 builder: &mut rowan::GreenNodeBuilder,
1486 indent: usize,
1487 flow_context: bool,
1488 ) -> bool {
1489 <&[YamlValue] as AsYaml>::build_content(&self.as_slice(), builder, indent, flow_context)
1490 }
1491
1492 fn is_inline(&self) -> bool {
1493 <&[YamlValue] as AsYaml>::is_inline(&self.as_slice())
1494 }
1495}
1496
1497impl AsYaml for &[YamlValue] {
1498 fn as_node(&self) -> Option<&SyntaxNode> {
1499 None
1500 }
1501
1502 fn kind(&self) -> YamlKind {
1503 YamlKind::Sequence
1504 }
1505
1506 fn build_content(
1507 &self,
1508 builder: &mut rowan::GreenNodeBuilder,
1509 indent: usize,
1510 _flow_context: bool,
1511 ) -> bool {
1512 use crate::lex::SyntaxKind;
1513
1514 let style = if self.is_empty() {
1515 CollectionStyle::Flow
1516 } else {
1517 CollectionStyle::Block
1518 };
1519
1520 builder.start_node(SyntaxKind::SEQUENCE.into());
1521
1522 match style {
1523 CollectionStyle::Flow => {
1524 builder.token(SyntaxKind::LEFT_BRACKET.into(), "[");
1525 builder.token(SyntaxKind::RIGHT_BRACKET.into(), "]");
1526 }
1527 CollectionStyle::Block => {
1528 let indent_str = " ".repeat(indent);
1529
1530 for (i, item) in self.iter().enumerate() {
1531 if i > 0 {
1532 builder.token(SyntaxKind::INDENT.into(), &indent_str);
1534 }
1535
1536 builder.start_node(SyntaxKind::SEQUENCE_ENTRY.into());
1537 builder.token(SyntaxKind::DASH.into(), "-");
1538 builder.token(SyntaxKind::WHITESPACE.into(), " ");
1539 let item_ends_with_newline =
1540 item.build_content(builder, indent + 2, _flow_context);
1541
1542 if !item_ends_with_newline {
1545 builder.token(SyntaxKind::NEWLINE.into(), "\n");
1546 }
1547
1548 builder.finish_node(); }
1550 }
1551 }
1552
1553 builder.finish_node(); matches!(style, CollectionStyle::Block) && !self.is_empty()
1556 }
1557
1558 fn is_inline(&self) -> bool {
1559 self.is_empty()
1560 }
1561}