|
72 | 72 | //! or not.
|
73 | 73 |
|
74 | 74 | use std::collections::{BTreeMap, HashMap};
|
| 75 | +use std::fmt; |
| 76 | +use std::fmt::Write; |
75 | 77 | use std::ops::Range;
|
76 | 78 |
|
77 | 79 | use ucd_parse::Codepoints;
|
@@ -222,7 +224,7 @@ fn main() {
|
222 | 224 | let ranges_by_property = &unicode_data.ranges;
|
223 | 225 |
|
224 | 226 | if let Some(path) = test_path {
|
225 |
| - std::fs::write(&path, generate_tests(&write_location, ranges_by_property)).unwrap(); |
| 227 | + std::fs::write(&path, generate_tests(ranges_by_property).unwrap()).unwrap(); |
226 | 228 | }
|
227 | 229 |
|
228 | 230 | let mut table_file = String::new();
|
@@ -326,66 +328,57 @@ fn fmt_list<V: std::fmt::Debug>(values: impl IntoIterator<Item = V>) -> String {
|
326 | 328 | out
|
327 | 329 | }
|
328 | 330 |
|
329 |
| -fn generate_tests(data_path: &str, ranges: &[(&str, Vec<Range<u32>>)]) -> String { |
| 331 | +fn generate_tests(ranges: &[(&str, Vec<Range<u32>>)]) -> Result<String, fmt::Error> { |
330 | 332 | let mut s = String::new();
|
331 |
| - s.push_str("#![allow(incomplete_features, unused)]\n"); |
332 |
| - s.push_str("#![feature(const_generics)]\n\n"); |
333 |
| - s.push_str("\n#[allow(unused)]\nuse std::hint;\n"); |
334 |
| - s.push_str(&format!("#[path = \"{data_path}\"]\n")); |
335 |
| - s.push_str("mod unicode_data;\n\n"); |
336 |
| - |
337 |
| - s.push_str("\nfn main() {\n"); |
338 |
| - |
| 333 | + writeln!(s, "#![feature(core_intrinsics)]")?; |
| 334 | + writeln!(s, "#![allow(internal_features, dead_code)]")?; |
| 335 | + writeln!(s, "// ignore-tidy-filelength")?; |
| 336 | + writeln!(s, "use std::intrinsics;")?; |
| 337 | + writeln!(s, "mod unicode_data;")?; |
| 338 | + writeln!(s, "fn main() {{")?; |
339 | 339 | for (property, ranges) in ranges {
|
340 |
| - s.push_str(&format!(r#" println!("Testing {property}");"#)); |
341 |
| - s.push('\n'); |
342 |
| - s.push_str(&format!(" {}_true();\n", property.to_lowercase())); |
343 |
| - s.push_str(&format!(" {}_false();\n", property.to_lowercase())); |
344 |
| - let mut is_true = Vec::new(); |
345 |
| - let mut is_false = Vec::new(); |
346 |
| - for ch_num in 0..(std::char::MAX as u32) { |
347 |
| - if std::char::from_u32(ch_num).is_none() { |
348 |
| - continue; |
349 |
| - } |
350 |
| - if ranges.iter().any(|r| r.contains(&ch_num)) { |
351 |
| - is_true.push(ch_num); |
352 |
| - } else { |
353 |
| - is_false.push(ch_num); |
354 |
| - } |
355 |
| - } |
356 |
| - |
357 |
| - s.push_str(&format!(" fn {}_true() {{\n", property.to_lowercase())); |
358 |
| - generate_asserts(&mut s, property, &is_true, true); |
359 |
| - s.push_str(" }\n\n"); |
360 |
| - s.push_str(&format!(" fn {}_false() {{\n", property.to_lowercase())); |
361 |
| - generate_asserts(&mut s, property, &is_false, false); |
362 |
| - s.push_str(" }\n\n"); |
| 340 | + let prop = property.to_lowercase(); |
| 341 | + writeln!(s, r#" println!("Testing {prop}");"#)?; |
| 342 | + writeln!(s, " {prop}_true();")?; |
| 343 | + writeln!(s, " {prop}_false();")?; |
| 344 | + let (is_true, is_false): (Vec<_>, Vec<_>) = (char::MIN..=char::MAX) |
| 345 | + .filter(|c| !c.is_ascii()) |
| 346 | + .map(u32::from) |
| 347 | + .partition(|c| ranges.iter().any(|r| r.contains(c))); |
| 348 | + |
| 349 | + writeln!(s, " fn {prop}_true() {{")?; |
| 350 | + generate_asserts(&mut s, &prop, &is_true, true)?; |
| 351 | + writeln!(s, " }}")?; |
| 352 | + |
| 353 | + writeln!(s, " fn {prop}_false() {{")?; |
| 354 | + generate_asserts(&mut s, &prop, &is_false, false)?; |
| 355 | + writeln!(s, " }}")?; |
363 | 356 | }
|
364 | 357 |
|
365 |
| - s.push('}'); |
366 |
| - s |
| 358 | + writeln!(s, "}}")?; |
| 359 | + Ok(s) |
367 | 360 | }
|
368 | 361 |
|
369 |
| -fn generate_asserts(s: &mut String, property: &str, points: &[u32], truthy: bool) { |
| 362 | +fn generate_asserts( |
| 363 | + s: &mut String, |
| 364 | + prop: &str, |
| 365 | + points: &[u32], |
| 366 | + truthy: bool, |
| 367 | +) -> Result<(), fmt::Error> { |
| 368 | + let truthy = if truthy { "" } else { "!" }; |
370 | 369 | for range in ranges_from_set(points) {
|
371 |
| - if range.end == range.start + 1 { |
372 |
| - s.push_str(&format!( |
373 |
| - " assert!({}unicode_data::{}::lookup({:?}), \"{}\");\n", |
374 |
| - if truthy { "" } else { "!" }, |
375 |
| - property.to_lowercase(), |
376 |
| - std::char::from_u32(range.start).unwrap(), |
377 |
| - range.start, |
378 |
| - )); |
379 |
| - } else { |
380 |
| - s.push_str(&format!(" for chn in {range:?}u32 {{\n")); |
381 |
| - s.push_str(&format!( |
382 |
| - " assert!({}unicode_data::{}::lookup(std::char::from_u32(chn).unwrap()), \"{{:?}}\", chn);\n", |
383 |
| - if truthy { "" } else { "!" }, |
384 |
| - property.to_lowercase(), |
385 |
| - )); |
386 |
| - s.push_str(" }\n"); |
| 370 | + let start = char::from_u32(range.start).unwrap(); |
| 371 | + let end = char::from_u32(range.end - 1).unwrap(); |
| 372 | + match range.len() { |
| 373 | + 1 => writeln!(s, " assert!({truthy}unicode_data::{prop}::lookup({start:?}));")?, |
| 374 | + _ => { |
| 375 | + writeln!(s, " for c in {start:?}..={end:?} {{")?; |
| 376 | + writeln!(s, " assert!({truthy}unicode_data::{prop}::lookup(c));")?; |
| 377 | + writeln!(s, " }}")?; |
| 378 | + } |
387 | 379 | }
|
388 | 380 | }
|
| 381 | + Ok(()) |
389 | 382 | }
|
390 | 383 |
|
391 | 384 | /// Group the elements of `set` into contigous ranges
|
|
0 commit comments