1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//! The Prisma Schema AST.

#![deny(rust_2018_idioms, unsafe_code)]
#![allow(clippy::derive_partial_eq_without_eq)]

pub use self::{parser::parse_schema, reformat::reformat, source_file::SourceFile};

/// The AST data structure. It aims to faithfully represent the syntax of a Prisma Schema, with
/// source span information.
pub mod ast;

mod parser;
mod reformat;
mod renderer;
mod source_file;

/// Transform the input string into a valid (quoted and escaped) PSL string literal.
///
/// PSL string literals have the exact same grammar as [JSON string
/// literals](https://datatracker.ietf.org/doc/html/rfc8259#section-7).
///
/// ```
/// # use schema_ast::string_literal;
///let input = r#"oh
///hi"#;
///assert_eq!(r#""oh\nhi""#, &string_literal(input).to_string());
/// ```
pub fn string_literal(s: &str) -> impl std::fmt::Display + '_ {
    struct StringLiteral<'a>(&'a str);

    impl std::fmt::Display for StringLiteral<'_> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            f.write_str("\"")?;
            for c in self.0.char_indices() {
                match c {
                    (_, '\t') => f.write_str("\\t")?,
                    (_, '\n') => f.write_str("\\n")?,
                    (_, '"') => f.write_str("\\\"")?,
                    (_, '\r') => f.write_str("\\r")?,
                    (_, '\\') => f.write_str("\\\\")?,
                    // Control characters
                    (_, c) if c.is_ascii_control() => {
                        let mut b = [0];
                        c.encode_utf8(&mut b);
                        f.write_fmt(format_args!("\\u{:04x}", b[0]))?;
                    }
                    (start, other) => f.write_str(&self.0[start..(start + other.len_utf8())])?,
                }
            }
            f.write_str("\"")
        }
    }

    StringLiteral(s)
}