Skip to main content

ephemeris_documents/yaml/
string.rs

1//! Style selection for string values.
2
3use super::literal::LiteralBlock;
4use super::scalar_text::ScalarText;
5use crate::annotation::StringStyle;
6
7/// How a string value is written.
8pub(super) enum YamlString<'a> {
9    Block(LiteralBlock<'a>),
10    Text(ScalarText<'a>),
11}
12
13impl<'a> YamlString<'a> {
14    /// Choose the form for `text`.
15    ///
16    /// A block is used when the text spans lines or the `Literal` style asks
17    /// for one, and a block can reproduce the text exactly. Everything else
18    /// is plain or double quoted.
19    pub(super) fn select(text: &'a str, style: StringStyle) -> Self {
20        let block = LiteralBlock::new(text);
21        let wanted = style == StringStyle::Literal || text.contains('\n');
22        if wanted && block.is_representable() {
23            Self::Block(block)
24        } else {
25            Self::Text(ScalarText::value(text))
26        }
27    }
28}
29
30#[cfg(test)]
31mod tests {
32    use super::YamlString;
33    use crate::annotation::StringStyle;
34
35    fn is_block(text: &str, style: StringStyle) -> bool {
36        matches!(YamlString::select(text, style), YamlString::Block(_))
37    }
38
39    #[test]
40    fn multiline_text_selects_a_block() {
41        assert!(is_block("a\nb", StringStyle::Plain));
42        assert!(is_block("a\n", StringStyle::Plain));
43    }
44
45    #[test]
46    fn single_line_text_is_plain_unless_literal() {
47        assert!(!is_block("a", StringStyle::Plain));
48        assert!(is_block("a", StringStyle::Literal));
49    }
50
51    #[test]
52    fn unrepresentable_text_falls_back_to_quotes() {
53        assert!(!is_block("a\r\nb", StringStyle::Plain));
54        assert!(!is_block("\n\n", StringStyle::Plain));
55    }
56}