graphql_toolkit_writer/fmt/
pretty.rs

1use std::io;
2
3use super::formatter::Formatter;
4use crate::ser::{Serialize, Serializer};
5
6/// This formatter generates a GraphQL document with a human-readable format.
7#[derive(Clone, Debug)]
8pub struct PrettyFormatter<'a> {
9    current_indent_level: usize,
10    indent: &'a [u8],
11}
12
13impl<'a> PrettyFormatter<'a> {
14    /// Construct a pretty printer formatter that defaults to using two spaces for indentation.
15    pub fn new() -> Self {
16        Default::default()
17    }
18
19    /// Construct a pretty printer formatter that uses the `indent` string for indentation.
20    pub fn with_indent(indent: &'a [u8]) -> Self {
21        PrettyFormatter {
22            current_indent_level: 0,
23            indent,
24        }
25    }
26}
27
28impl<'a> Default for PrettyFormatter<'a> {
29    fn default() -> Self {
30        PrettyFormatter::with_indent(b"  ")
31    }
32}
33
34impl<'a> Formatter for PrettyFormatter<'a> {
35    #[inline]
36    fn before_operation_or_fragment_definition<W>(&mut self, writer: &mut W) -> io::Result<()>
37    where
38        W: ?Sized + io::Write,
39    {
40        writer.write_all(b"\n")
41    }
42
43    #[inline]
44    fn before_operation_variable_definitions<W>(&mut self, writer: &mut W) -> io::Result<()>
45    where
46        W: ?Sized + io::Write,
47    {
48        writer.write_all(b" ")
49    }
50
51    #[inline]
52    fn after_operation_or_fragment_signature<W>(&mut self, writer: &mut W) -> io::Result<()>
53    where
54        W: ?Sized + io::Write,
55    {
56        writer.write_all(b" ")
57    }
58
59    #[inline]
60    fn after_selection_signature<W>(&mut self, writer: &mut W) -> io::Result<()>
61    where
62        W: ?Sized + io::Write,
63    {
64        writer.write_all(b" ")
65    }
66
67    #[inline]
68    fn before_type_condition<W>(&mut self, writer: &mut W) -> io::Result<()>
69    where
70        W: ?Sized + io::Write,
71    {
72        writer.write_all(b" ")
73    }
74
75    #[inline]
76    fn before_directive<W>(&mut self, writer: &mut W) -> io::Result<()>
77    where
78        W: ?Sized + io::Write,
79    {
80        writer.write_all(b" ")
81    }
82
83    fn write_name_value_separator<W>(&mut self, writer: &mut W) -> io::Result<()>
84    where
85        W: ?Sized + io::Write,
86    {
87        writer.write_all(b": ")
88    }
89
90    fn write_variable_default_value_separator<W>(&mut self, writer: &mut W) -> io::Result<()>
91    where
92        W: ?Sized + io::Write,
93    {
94        writer.write_all(b" = ")
95    }
96
97    fn write_item_separator<W>(&mut self, writer: &mut W) -> io::Result<()>
98    where
99        W: ?Sized + io::Write,
100    {
101        writer.write_all(b", ")
102    }
103
104    #[inline]
105    fn begin_block<W>(&mut self, writer: &mut W) -> io::Result<()>
106    where
107        W: ?Sized + io::Write,
108    {
109        self.current_indent_level += 1;
110
111        writer.write_all(b"{\n")
112    }
113
114    #[inline]
115    fn end_block<W>(&mut self, writer: &mut W) -> io::Result<()>
116    where
117        W: ?Sized + io::Write,
118    {
119        writer.write_all(b"\n")?;
120
121        self.current_indent_level -= 1;
122        indent(writer, self.current_indent_level, self.indent)?;
123
124        writer.write_all(b"}")
125    }
126
127    #[inline]
128    fn before_block_item<W>(&mut self, writer: &mut W) -> io::Result<()>
129    where
130        W: ?Sized + io::Write,
131    {
132        indent(writer, self.current_indent_level, self.indent)
133    }
134
135    #[inline]
136    fn after_block_item<W>(&mut self, writer: &mut W) -> io::Result<()>
137    where
138        W: ?Sized + io::Write,
139    {
140        writer.write_all(b"\n")
141    }
142}
143
144/// Indent the specified writer `n` times by the `s` number of spaces.
145fn indent<W>(writer: &mut W, n: usize, indent: &[u8]) -> io::Result<()>
146where
147    W: ?Sized + io::Write,
148{
149    for _ in 0..n {
150        writer.write_all(indent)?;
151    }
152
153    Ok(())
154}
155
156/// Serialize the given GraphQL AST as a pretty-printed GraphQL document into the I/O stream.
157#[inline]
158pub fn to_writer_pretty<W, T>(writer: W, value: &T) -> anyhow::Result<()>
159where
160    W: io::Write,
161    T: ?Sized + Serialize,
162{
163    let mut ser = Serializer::with_formatter(writer, PrettyFormatter::new());
164    value.serialize(&mut ser)
165}
166
167/// Serialize the given GraphQL AST as a pretty-printed GraphQL document byte vector.
168#[inline]
169pub fn to_vec_pretty<T>(value: &T) -> anyhow::Result<Vec<u8>>
170where
171    T: ?Sized + Serialize,
172{
173    let mut writer = Vec::with_capacity(128);
174    to_writer_pretty(&mut writer, value)?;
175    Ok(writer)
176}
177
178/// Serialize the given GraphQL AST as a pretty-printed GraphQL document string.
179#[inline]
180pub fn to_string_pretty<T>(value: &T) -> anyhow::Result<String>
181where
182    T: ?Sized + Serialize,
183{
184    let vec = to_vec_pretty(value)?;
185    let string = unsafe {
186        // We do not emit invalid UTF-8.
187        String::from_utf8_unchecked(vec)
188    };
189    Ok(string)
190}