1
use ron::{
2
    de::from_bytes,
3
    error::{Error, Position, Span, SpannedError},
4
    from_str, to_string,
5
    value::RawValue,
6
};
7
use serde::{Deserialize, Serialize};
8

            
9
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
10
struct WithRawValue {
11
    a: bool,
12
    b: Box<RawValue>,
13
}
14

            
15
#[test]
16
4
fn test_raw_value_simple() {
17
4
    let raw: &RawValue = from_str("true").unwrap();
18
4
    assert_eq!(raw.get_ron(), "true");
19
4
    let ser = to_string(raw).unwrap();
20
4
    assert_eq!(ser, "true");
21
4
}
22

            
23
#[test]
24
4
fn test_raw_value_inner() {
25
4
    let raw: WithRawValue = from_str("(a: false, b: [1, /* lol */ 2, 3])").unwrap();
26
4
    assert_eq!(raw.b.get_ron(), "[1, /* lol */ 2, 3]");
27
4
    let ser = to_string(&raw).unwrap();
28
4
    assert_eq!(ser, "(a:false,b:[1, /* lol */ 2, 3])");
29
4
}
30

            
31
#[test]
32
4
fn test_raw_value_comment() {
33
4
    let raw: WithRawValue = from_str("(a: false, b: /* yeah */ 4)").unwrap();
34
4
    assert_eq!(raw.b.get_ron(), "/* yeah */ 4");
35

            
36
4
    let raw: WithRawValue = from_str("(a: false, b: 4 /* yes */)").unwrap();
37
4
    assert_eq!(raw.b.get_ron(), "4 /* yes */");
38

            
39
4
    let raw: WithRawValue = from_str("(a: false, b: (/* this */ 4 /* too */))").unwrap();
40
4
    assert_eq!(raw.b.get_ron(), "(/* this */ 4 /* too */)");
41
4
}
42

            
43
#[test]
44
4
fn test_raw_value_invalid() {
45
4
    let err = from_str::<&RawValue>("4.d").unwrap_err();
46
4
    assert_eq!(
47
        err,
48
        SpannedError {
49
            code: Error::TrailingCharacters,
50
            span: Span {
51
                start: Position { line: 1, col: 3 },
52
                end: Position { line: 1, col: 3 }
53
            }
54
        }
55
    );
56

            
57
4
    let err = from_bytes::<&RawValue>(b"\0").unwrap_err();
58
4
    assert_eq!(
59
        err,
60
        SpannedError {
61
            code: Error::UnexpectedChar('\0'),
62
            span: Span {
63
                start: Position { line: 1, col: 1 },
64
                end: Position { line: 1, col: 1 }
65
            }
66
        }
67
    )
68
4
}
69

            
70
#[test]
71
4
fn test_raw_value_from_ron() {
72
4
    let raw = RawValue::from_ron("/* hi */ (None, 4.2) /* bye */").unwrap();
73
4
    assert_eq!(raw.get_ron(), "/* hi */ (None, 4.2) /* bye */");
74

            
75
4
    let err = RawValue::from_ron("4.d").unwrap_err();
76
4
    assert_eq!(
77
        err,
78
        SpannedError {
79
            code: Error::TrailingCharacters,
80
            span: Span {
81
                start: Position { line: 1, col: 3 },
82
                end: Position { line: 1, col: 3 }
83
            }
84
        }
85
    );
86

            
87
4
    let raw =
88
4
        RawValue::from_boxed_ron(String::from("/* hi */ (None, 4.2) /* bye */").into_boxed_str())
89
4
            .unwrap();
90
4
    assert_eq!(raw.get_ron(), "/* hi */ (None, 4.2) /* bye */");
91

            
92
4
    let err = RawValue::from_boxed_ron(String::from("(").into_boxed_str()).unwrap_err();
93
4
    assert_eq!(
94
        err,
95
        SpannedError {
96
            code: Error::Eof,
97
            span: Span {
98
                start: Position { line: 1, col: 1 },
99
                end: Position { line: 1, col: 2 },
100
            }
101
        }
102
    );
103
4
}
104

            
105
#[test]
106
4
fn test_raw_value_into_rust() {
107
4
    let raw = RawValue::from_ron("/* hi */ (a: false, b: None) /* bye */").unwrap();
108

            
109
4
    let with: WithRawValue = raw.into_rust().unwrap();
110
4
    assert_eq!(
111
        with,
112
4
        WithRawValue {
113
4
            a: false,
114
4
            b: from_str("None").unwrap(),
115
4
        }
116
    );
117

            
118
4
    let err = raw.into_rust::<i32>().unwrap_err();
119
4
    assert_eq!(
120
        err,
121
        SpannedError {
122
            code: Error::ExpectedInteger,
123
            span: Span {
124
                start: Position { line: 1, col: 9 },
125
                end: Position { line: 1, col: 10 },
126
            }
127
        }
128
    );
129
4
}
130

            
131
#[test]
132
4
fn test_raw_value_from_rust() {
133
4
    let raw = RawValue::from_rust(&42).unwrap();
134
4
    assert_eq!(raw.get_ron(), "42");
135

            
136
4
    let raw = RawValue::from_rust(&WithRawValue {
137
4
        a: true,
138
4
        b: from_str("4.2").unwrap(),
139
4
    })
140
4
    .unwrap();
141
4
    assert_eq!(raw.get_ron(), "(a:true,b:4.2)");
142
4
}
143

            
144
#[test]
145
4
fn test_raw_value_serde_json() {
146
4
    let raw = RawValue::from_ron("/* hi */ (None, 4.2) /* bye */").unwrap();
147

            
148
4
    let ser = serde_json::to_string(&WithRawValue {
149
4
        a: true,
150
4
        b: raw.to_owned(),
151
4
    })
152
4
    .unwrap();
153
4
    assert_eq!(ser, "{\"a\":true,\"b\":\"/* hi */ (None, 4.2) /* bye */\"}");
154

            
155
4
    let with: WithRawValue = serde_json::from_str(&ser).unwrap();
156
4
    assert_eq!(raw, &*with.b);
157

            
158
4
    let err =
159
4
        serde_json::from_str::<WithRawValue>("{\"a\":true,\"b\":\"/* hi */ (a:) /* bye */\"}")
160
4
            .unwrap_err();
161
4
    assert_eq!(
162
4
        err.to_string(),
163
        "invalid RON value at 1:13: Unexpected char ')' at line 1 column 39"
164
    );
165

            
166
4
    let err = serde_json::from_str::<WithRawValue>("{\"a\":true,\"b\":42}").unwrap_err();
167
4
    assert_eq!(
168
4
        err.to_string(),
169
        "invalid type: integer `42`, expected any valid RON-value-string at line 1 column 16"
170
    );
171

            
172
4
    let err = serde_json::from_str::<&RawValue>("\"/* hi */ (a:) /* bye */\"").unwrap_err();
173
4
    assert_eq!(
174
4
        err.to_string(),
175
        "invalid RON value at 1:13: Unexpected char ')' at line 1 column 25"
176
    );
177

            
178
4
    let err = serde_json::from_str::<&RawValue>("42").unwrap_err();
179
4
    assert_eq!(
180
4
        err.to_string(),
181
        "invalid type: integer `42`, expected any valid borrowed RON-value-string at line 1 column 2"
182
    );
183
4
}
184

            
185
#[test]
186
4
fn test_raw_value_serde_json_same_checks_as_from_ron() {
187
    // an unclosed line comment would swallow the rest of the line on serialisation
188
4
    let err = serde_json::from_str::<WithRawValue>("{\"a\":true,\"b\":\"42 //\"}").unwrap_err();
189
4
    assert!(err.to_string().contains("unclosed line comment"), "{}", err);
190
4
    let err = serde_json::from_str::<&RawValue>("\"42 //\"").unwrap_err();
191
4
    assert!(err.to_string().contains("unclosed line comment"), "{}", err);
192
4
    let err =
193
4
        Box::<RawValue>::deserialize(serde::de::value::StrDeserializer::<Error>::new("42 //"))
194
4
            .unwrap_err();
195
4
    assert!(err.to_string().contains("unclosed line comment"), "{}", err);
196

            
197
    // extensions cannot be enabled inside a raw value
198
4
    let err =
199
4
        serde_json::from_str::<WithRawValue>("{\"a\":true,\"b\":\"#![enable(implicit_some)] 42\"}")
200
4
            .unwrap_err();
201
4
    assert!(
202
4
        err.to_string().contains("cannot enable extensions"),
203
        "{}",
204
        err
205
    );
206

            
207
4
    let with: WithRawValue = serde_json::from_str("{\"a\":true,\"b\":\"42 //\\n\"}").unwrap();
208
4
    assert_eq!(with.b.get_ron(), "42 //\n");
209
4
    assert_eq!(
210
4
        ron::from_str::<WithRawValue>(&ron::to_string(&with).unwrap())
211
4
            .unwrap()
212
4
            .b
213
4
            .get_ron(),
214
        "42 //\n"
215
    );
216
4
}
217

            
218
#[test]
219
4
fn test_raw_value_rejects_ignored_attributes() {
220
    // leading whitespace and comments are still fine
221
4
    assert_eq!(
222
4
        RawValue::from_ron(" /* a */ 42").unwrap().get_ron(),
223
        " /* a */ 42"
224
    );
225

            
226
    // the attribute would end up in the middle of the serialised document
227
8
    for ron in ["#![type = \"x\"] 42", " #![schema = \"s.ron\"] (a: 1)"] {
228
8
        let err = RawValue::from_ron(ron).unwrap_err();
229
8
        assert_eq!(
230
            err.code,
231
8
            Error::Message(String::from(
232
8
                "ron::value::RawValue cannot contain attributes"
233
8
            ))
234
        );
235
8
        assert!(RawValue::from_boxed_ron(String::from(ron).into_boxed_str()).is_err());
236
    }
237

            
238
4
    let err =
239
4
        serde_json::from_str::<WithRawValue>("{\"a\":true,\"b\":\"#![type = \\\"x\\\"] 42\"}")
240
4
            .unwrap_err();
241
4
    assert!(
242
4
        err.to_string().contains("cannot contain attributes"),
243
        "{}",
244
        err
245
    );
246

            
247
    // attributes are still allowed at the start of a document holding a raw value
248
4
    let with: WithRawValue = ron::from_str("#![type = \"x\"] (a: true, b: 42)").unwrap();
249
4
    assert_eq!(with.b.get_ron(), "42");
250
4
}
251

            
252
#[test]
253
4
fn test_raw_value_clone_into() {
254
4
    let raw = RawValue::from_boxed_ron(String::from("(None, 4.2)").into_boxed_str()).unwrap();
255
4
    let raw2 = raw.clone();
256
4
    assert_eq!(raw, raw2);
257

            
258
4
    let boxed_str: Box<str> = raw2.into();
259
4
    assert_eq!(&*boxed_str, "(None, 4.2)");
260
4
}
261

            
262
#[test]
263
4
fn test_raw_value_debug_display() {
264
4
    let raw = RawValue::from_ron("/* hi */ (None, 4.2) /* bye */").unwrap();
265

            
266
4
    assert_eq!(format!("{}", raw), "/* hi */ (None, 4.2) /* bye */");
267
4
    assert_eq!(
268
4
        format!("{:#?}", raw),
269
        "\
270
RawValue(
271
    /* hi */ (None, 4.2) /* bye */,
272
)\
273
    "
274
    );
275
4
}
276

            
277
#[test]
278
4
fn test_boxed_raw_value_deserialise_from_string() {
279
4
    let string = serde::de::value::StringDeserializer::<Error>::new(String::from("4.2"));
280

            
281
4
    let err = <&RawValue>::deserialize(string.clone()).unwrap_err();
282
4
    assert_eq!(
283
        err,
284
4
        Error::InvalidValueForType {
285
4
            expected: String::from("any valid borrowed RON-value-string"),
286
4
            found: String::from("the string \"4.2\""),
287
4
        }
288
    );
289

            
290
4
    let boxed_raw = Box::<RawValue>::deserialize(string).unwrap();
291
4
    assert_eq!(boxed_raw.get_ron(), "4.2");
292

            
293
4
    let string = serde::de::value::StringDeserializer::<Error>::new(String::from("["));
294

            
295
4
    let err = Box::<RawValue>::deserialize(string).unwrap_err();
296
4
    assert_eq!(
297
        err,
298
4
        Error::Message(String::from(
299
4
            "invalid RON value at 1:1-1:2: Unexpected end of RON"
300
4
        ))
301
    );
302
4
}
303

            
304
#[test]
305
4
fn test_whitespace_rountrip_issues_and_trim() {
306
4
    let mut v = WithRawValue {
307
4
        a: true,
308
4
        b: RawValue::from_ron("42 ").unwrap().to_owned(),
309
4
    };
310
4
    v = ron::from_str(&ron::to_string(&v).unwrap()).unwrap();
311
4
    assert_eq!(v.b.get_ron(), "42");
312
4
    assert_eq!(v.b.trim().get_ron(), "42");
313
4
    assert_eq!(v.b.to_owned().trim_boxed().get_ron(), "42");
314

            
315
4
    for _ in 1..=10 {
316
40
        v = ron::from_str(
317
40
            &ron::ser::to_string_pretty(&v, ron::ser::PrettyConfig::default()).unwrap(),
318
        )
319
40
        .unwrap();
320
40
        assert_eq!(v.b.get_ron(), "42");
321
40
        assert_eq!(v.b.trim().get_ron(), "42");
322
40
        assert_eq!(v.b.to_owned().trim_boxed().get_ron(), "42");
323
    }
324

            
325
4
    assert_eq!(RawValue::from_ron("42").unwrap().trim().get_ron(), "42");
326
4
    assert_eq!(
327
4
        RawValue::from_ron(" /* start */ 42    // end\n ")
328
4
            .unwrap()
329
4
            .trim()
330
4
            .get_ron(),
331
        "42"
332
    );
333

            
334
4
    assert_eq!(
335
4
        RawValue::from_ron("42")
336
4
            .unwrap()
337
4
            .to_owned()
338
4
            .trim_boxed()
339
4
            .get_ron(),
340
        "42"
341
    );
342
4
    assert_eq!(
343
4
        RawValue::from_ron(" /* start */ 42    // end\n ")
344
4
            .unwrap()
345
4
            .to_owned()
346
4
            .trim_boxed()
347
4
            .get_ron(),
348
        "42"
349
    );
350
4
    assert_eq!(
351
4
        RawValue::from_ron("\u{2028}/* ä */\u{85}\"ö\"\u{2029}// ü\n\u{200E}")
352
4
            .unwrap()
353
4
            .to_owned()
354
4
            .trim_boxed()
355
4
            .get_ron(),
356
        "\"ö\""
357
    );
358
4
}
359

            
360
#[test]
361
4
fn test_fuzzer_found_issue() {
362
4
    assert_eq!(
363
4
        RawValue::from_ron(""),
364
        Err(SpannedError {
365
            code: Error::Eof,
366
            span: Span {
367
                start: Position { line: 1, col: 1 },
368
                end: Position { line: 1, col: 1 },
369
            }
370
        })
371
    );
372

            
373
4
    assert_eq!(ron::from_str("C"), RawValue::from_ron("C"));
374

            
375
4
    assert_eq!(ron::from_str(" t "), RawValue::from_ron(" t "));
376

            
377
4
    assert_eq!(
378
4
        RawValue::from_ron("#![enable(implicit_some)] 42"),
379
4
        Err(SpannedError {
380
4
            code: Error::Message(String::from(
381
4
                "ron::value::RawValue cannot enable extensions"
382
4
            )),
383
4
            span: Span {
384
4
                start: Position { line: 1, col: 27 },
385
4
                end: Position { line: 1, col: 27 },
386
4
            }
387
4
        })
388
    );
389

            
390
4
    assert_eq!(
391
4
        RawValue::from_boxed_ron(String::from("#![enable(implicit_some)] 42").into_boxed_str()),
392
4
        Err(SpannedError {
393
4
            code: Error::Message(String::from(
394
4
                "ron::value::RawValue cannot enable extensions"
395
4
            )),
396
4
            span: Span {
397
4
                start: Position { line: 1, col: 27 },
398
4
                end: Position { line: 1, col: 27 },
399
4
            }
400
4
        })
401
    );
402

            
403
4
    assert_eq!(
404
4
        RawValue::from_ron("42 //"),
405
        Err(SpannedError {
406
            code: Error::UnclosedLineComment,
407
            span: Span {
408
                start: Position { line: 1, col: 6 },
409
                end: Position { line: 1, col: 6 },
410
            }
411
        })
412
    );
413
4
    assert_eq!(
414
4
        ron::from_str::<&RawValue>("42 //"),
415
        Err(SpannedError {
416
            code: Error::UnclosedLineComment,
417
            span: Span {
418
                start: Position { line: 1, col: 6 },
419
                end: Position { line: 1, col: 6 },
420
            }
421
        })
422
    );
423
4
    assert_eq!(
424
4
        ron::from_str::<&RawValue>("42 //\n").unwrap(),
425
4
        RawValue::from_ron("42 //\n").unwrap()
426
    );
427
4
    assert_eq!(
428
4
        ron::from_str::<&RawValue>("42 /**/").unwrap(),
429
4
        RawValue::from_ron("42 /**/").unwrap()
430
    );
431
4
    assert_eq!(
432
4
        ron::from_str::<&RawValue>("42 ").unwrap(),
433
4
        RawValue::from_ron("42 ").unwrap()
434
    );
435

            
436
4
    assert_eq!(
437
4
        RawValue::from_ron("a//"),
438
        Err(SpannedError {
439
            code: Error::UnclosedLineComment,
440
            span: Span {
441
                start: Position { line: 1, col: 4 },
442
                end: Position { line: 1, col: 4 },
443
            }
444
        })
445
    );
446
4
    assert_eq!(
447
4
        ron::from_str::<&RawValue>("a//"),
448
        Err(SpannedError {
449
            code: Error::UnclosedLineComment,
450
            span: Span {
451
                start: Position { line: 1, col: 4 },
452
                end: Position { line: 1, col: 4 },
453
            }
454
        })
455
    );
456
4
    assert_eq!(
457
4
        ron::from_str::<&RawValue>("a//\n").unwrap(),
458
4
        RawValue::from_ron("a//\n").unwrap()
459
    );
460
4
    assert_eq!(
461
4
        ron::from_str::<&RawValue>("a/**/").unwrap(),
462
4
        RawValue::from_ron("a/**/").unwrap()
463
    );
464
4
    assert_eq!(
465
4
        ron::from_str::<&RawValue>("a").unwrap(),
466
4
        RawValue::from_ron("a").unwrap()
467
    );
468

            
469
4
    assert_eq!(
470
4
        ron::to_string(&Some(Some(RawValue::from_ron("None").unwrap()))).unwrap(),
471
        "Some(Some(None))"
472
    );
473
    // Since a RawValue can contain anything, no implicit Some are allowed around it
474
4
    assert_eq!(
475
4
        ron::Options::default()
476
4
            .with_default_extension(ron::extensions::Extensions::IMPLICIT_SOME)
477
4
            .to_string(&Some(Some(RawValue::from_ron("None").unwrap())))
478
4
            .unwrap(),
479
        "Some(Some(None))"
480
    );
481
4
    assert_eq!(
482
4
        ron::from_str::<Option<Option<&RawValue>>>("Some(Some(None))").unwrap(),
483
4
        Some(Some(RawValue::from_ron("None").unwrap()))
484
    );
485
4
}
486

            
487
#[test]
488
4
fn test_raw_value_trims_surrounding_whitespace() {
489
4
    let raw: WithRawValue = from_str("(a: false, b:   [1, 2]  \n )").unwrap();
490
4
    assert_eq!(raw.b.get_ron(), "[1, 2]");
491

            
492
    // line comments must stay closed
493
4
    let raw: WithRawValue = from_str("(a: false, b: 4 // yes\n  \n )").unwrap();
494
4
    assert_eq!(raw.b.get_ron(), "4 // yes\n");
495

            
496
    // ... including when there is extra whitespace before the first line break
497
4
    let raw: WithRawValue = from_str("(a: false, b: 4   // yes  \n  \n )").unwrap();
498
4
    assert_eq!(raw.b.get_ron(), "4   // yes  \n");
499

            
500
4
    let raw: WithRawValue = from_str("(a: false, b:\n  // so\n  4  )").unwrap();
501
4
    assert_eq!(raw.b.get_ron(), "// so\n  4");
502
4
}
503

            
504
#[test]
505
4
fn test_raw_value_pretty_roundtrip_is_stable() {
506
4
    let config = ron::ser::PrettyConfig::default();
507

            
508
12
    for ron in [
509
4
        "(a: false, b: [1, 2])",
510
4
        "(a: false, b: /* hi */ [1, 2] /* bye */)",
511
4
        "(a: false, b: 4 // bye\n)",
512
4
    ] {
513
12
        let first =
514
12
            ron::ser::to_string_pretty(&from_str::<WithRawValue>(ron).unwrap(), config.clone())
515
12
                .unwrap();
516
12
        let second =
517
12
            ron::ser::to_string_pretty(&from_str::<WithRawValue>(&first).unwrap(), config.clone())
518
12
                .unwrap();
519
12
        assert_eq!(first, second);
520
    }
521

            
522
4
    let first = ron::ser::to_string_pretty(
523
4
        &from_str::<WithRawValue>("(a: false, b: [1, 2])").unwrap(),
524
4
        config,
525
    )
526
4
    .unwrap();
527
4
    assert_eq!(first, "(\n    a: false,\n    b: [1, 2],\n)");
528
4
}