bluejay-printer 0.3.1

A GraphQL printer
Documentation
use crate::write_indent;
use std::fmt::{Display, Formatter, Result};

pub(crate) struct StringValuePrinter<'a>(&'a str);

impl<'a> StringValuePrinter<'a> {
    pub(crate) fn new(value: &'a str) -> Self {
        Self(value)
    }
}

impl Display for StringValuePrinter<'_> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        let Self(value) = *self;
        write!(f, "\"")?;
        value.chars().try_for_each(|c| match c {
            '\"' | '\\' => write!(f, "\\{c}"),
            '\u{0008}' => write!(f, "\\b"),
            '\u{000C}' => write!(f, "\\f"),
            '\n' => write!(f, "\\n"),
            '\r' => write!(f, "\\r"),
            '\t' => write!(f, "\\t"),
            c => write!(f, "{c}"),
        })?;
        write!(f, "\"")
    }
}

pub(crate) struct BlockStringValuePrinter<'a> {
    value: &'a str,
    indentation: usize,
}

impl<'a> BlockStringValuePrinter<'a> {
    pub(crate) fn new(value: &'a str, indentation: usize) -> Self {
        Self { value, indentation }
    }
}

impl Display for BlockStringValuePrinter<'_> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        let Self { value, indentation } = *self;
        write_indent(f, indentation)?;
        writeln!(f, "\"\"\"")?;

        let escaped = value.replace("\"\"\"", "\\\"\"\"");

        escaped.lines().try_for_each(|line| {
            write_indent(f, indentation)?;
            writeln!(f, "{line}")
        })?;

        write_indent(f, indentation)?;
        writeln!(f, "\"\"\"")
    }
}

#[cfg(test)]
mod tests {
    use super::BlockStringValuePrinter;

    fn assert_prints_block(expected_output: &str, input: &str, indentation: usize) {
        let output = BlockStringValuePrinter::new(input, indentation).to_string();
        assert_eq!(expected_output, output);
    }

    #[test]
    fn test_block() {
        assert_prints_block("\"\"\"\n\"\"\"\n", "", 0);
        assert_prints_block("    \"\"\"\n    \"\"\"\n", "", 4);
        assert_prints_block(
            "\"\"\"\nThis\nis\na\nmultiline\nstring\n\"\"\"\n",
            "This\nis\na\nmultiline\nstring",
            0,
        );
        assert_prints_block("\"\"\"\n\\\"\"\"\n\"\"\"\n", "\"\"\"", 0);
    }
}