cargo_cargofmt/formatting/
string.rs1use std::borrow::Cow;
2
3use toml_writer::TomlWrite as _;
4
5use crate::toml::TokenKind;
6
7#[tracing::instrument]
8pub fn normalize_strings(tokens: &mut crate::toml::TomlTokens<'_>) {
9 for i in tokens.indices() {
10 let token = &mut tokens.tokens[i];
11 match token.kind {
12 TokenKind::StdTableOpen | TokenKind::ArrayTableOpen => {}
13 TokenKind::ArrayOpen | TokenKind::InlineTableOpen => {}
14 TokenKind::StdTableClose | TokenKind::ArrayTableClose => {}
15 TokenKind::ArrayClose | TokenKind::InlineTableClose => {}
16 TokenKind::SimpleKey => {
17 if token.encoding.is_some() {
18 let mut new_raw = String::new();
19 new_raw
20 .key(
21 toml_writer::TomlKeyBuilder::new(token.decoded.as_ref().unwrap())
22 .as_default(),
23 )
24 .unwrap();
25 token.raw = Cow::Owned(new_raw);
26 }
27 }
28 TokenKind::KeySep => {}
29 TokenKind::KeyValSep => {}
30 TokenKind::Scalar => {
31 if let Some(decoded) = token.decoded.as_ref() {
32 let mut new_raw = String::new();
33 new_raw
34 .value(toml_writer::TomlStringBuilder::new(decoded).as_default())
35 .unwrap();
36 token.raw = Cow::Owned(new_raw);
37 }
38 }
39 TokenKind::ValueSep => {}
40 TokenKind::Whitespace => {}
41 TokenKind::Comment => {}
42 TokenKind::Newline => {}
43 TokenKind::Error => {}
44 }
45 }
46}
47
48#[cfg(test)]
49mod test {
50 use snapbox::assert_data_eq;
51 use snapbox::str;
52 use snapbox::IntoData;
53
54 #[track_caller]
55 fn valid(input: &str, expected: impl IntoData) {
56 let mut tokens = crate::toml::TomlTokens::parse(input);
57 super::normalize_strings(&mut tokens);
58 let actual = tokens.to_string();
59
60 assert_data_eq!(&actual, expected);
61
62 let (_, errors) = toml::de::DeTable::parse_recoverable(&actual);
63 if !errors.is_empty() {
64 use std::fmt::Write as _;
65 let mut result = String::new();
66 writeln!(&mut result, "---").unwrap();
67 for error in errors {
68 writeln!(&mut result, "{error}").unwrap();
69 writeln!(&mut result, "---").unwrap();
70 }
71 panic!("failed to parse\n---\n{actual}\n{result}");
72 }
73 }
74
75 #[test]
76 fn empty() {
77 valid("", str![]);
78 }
79
80 #[test]
81 fn bare_key() {
82 valid(
83 r#"
84a = "value"
85"#,
86 str![[r#"
87
88a = "value"
89
90"#]],
91 );
92 }
93
94 #[test]
95 fn normalize_key_basic() {
96 valid(
97 r#"
98"" = "value"
99"b" = "value"
100"c'" = "value"
101"d\"" = "value"
102"#,
103 str![[r#"
104
105"" = "value"
106b = "value"
107"c'" = "value"
108'd"' = "value"
109
110"#]],
111 );
112 }
113
114 #[test]
115 fn normalize_key_literal() {
116 valid(
117 r#"
118'' = "value"
119'b' = "value"
120'd"' = "value"
121"#,
122 str![[r#"
123
124"" = "value"
125b = "value"
126'd"' = "value"
127
128"#]],
129 );
130 }
131
132 #[test]
133 fn normalize_value_string_type() {
134 valid(
135 r#"
136a = "value"
137b = 'value'
138c = """value"""
139d = """
140value"""
141e = '''value'''
142f = '''
143value'''
144"#,
145 str![[r#"
146
147a = "value"
148b = "value"
149c = "value"
150d = "value"
151e = "value"
152f = "value"
153
154"#]],
155 );
156 }
157
158 #[test]
159 fn normalize_value_escape() {
160 valid(
161 r#"
162a = "a\"b"
163b = 'a"b'
164c = """a\"b"""
165d = """
166a\"b"""
167e = '''a"b'''
168f = '''
169a"b'''
170"#,
171 str![[r#"
172
173a = 'a"b'
174b = 'a"b'
175c = 'a"b'
176d = 'a"b'
177e = 'a"b'
178f = 'a"b'
179
180"#]],
181 );
182 }
183
184 #[test]
185 fn normalize_value_multi_leading_nl() {
186 valid(
187 r#"
188a = """ab"""
189b = """a\nb"""
190c = """a
191b
192"""
193d = """
194a
195b
196"""
197e = '''ab'''
198f = '''a
199b
200'''
201g = '''
202a
203b
204'''
205"#,
206 str![[r#"
207
208a = "ab"
209b = """
210a
211b"""
212c = """
213a
214b
215"""
216d = """
217a
218b
219"""
220e = "ab"
221f = """
222a
223b
224"""
225g = """
226a
227b
228"""
229
230"#]],
231 );
232 }
233}