pg2sqlite_core/diagnostics/
reporter.rs1use std::io::Write;
3use std::path::Path;
4
5use super::warning::{Severity, Warning};
6
7pub fn report_warnings(
9 warnings: &[Warning],
10 destination: &WarningDestination,
11) -> std::io::Result<()> {
12 if warnings.is_empty() {
13 return Ok(());
14 }
15
16 let mut sorted = warnings.to_vec();
17 sorted.sort_by(|a, b| a.object.cmp(&b.object).then_with(|| a.code.cmp(b.code)));
18
19 match destination {
20 WarningDestination::Stderr => {
21 let stderr = std::io::stderr();
22 let mut handle = stderr.lock();
23 for w in &sorted {
24 writeln!(handle, "{w}")?;
25 }
26 }
27 WarningDestination::File(path) => {
28 let mut file = std::fs::File::create(path)?;
29 for w in &sorted {
30 writeln!(file, "{w}")?;
31 }
32 }
33 }
34
35 Ok(())
36}
37
38pub fn check_strict(warnings: &[Warning]) -> Result<(), StrictViolation> {
40 let violations: Vec<&Warning> = warnings
41 .iter()
42 .filter(|w| w.severity >= Severity::Lossy)
43 .collect();
44
45 if violations.is_empty() {
46 Ok(())
47 } else {
48 let messages: Vec<String> = violations.iter().map(|w| w.to_string()).collect();
49 Err(StrictViolation { messages })
50 }
51}
52
53#[derive(Debug)]
55pub struct StrictViolation {
56 pub messages: Vec<String>,
57}
58
59impl std::fmt::Display for StrictViolation {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 writeln!(
62 f,
63 "Strict mode: {} lossy conversion(s) found:",
64 self.messages.len()
65 )?;
66 for msg in &self.messages {
67 writeln!(f, " {msg}")?;
68 }
69 Ok(())
70 }
71}
72
73impl std::error::Error for StrictViolation {}
74
75pub enum WarningDestination {
77 Stderr,
78 File(std::path::PathBuf),
79}
80
81impl WarningDestination {
82 pub fn from_option(path: Option<&Path>) -> Self {
83 match path {
84 Some(p) if p.to_str() == Some("stderr") => WarningDestination::Stderr,
85 Some(p) => WarningDestination::File(p.to_path_buf()),
86 None => WarningDestination::Stderr,
87 }
88 }
89}