1use std::fmt;
2
3#[derive(Debug)]
4pub struct Error {
5 pub kind: &'static str,
6 pub message: String,
7 pub page_id: Option<String>,
8}
9
10pub const CONTRACTS: &[(&str, i32, &str)] = &[
11 ("invalid_input", 2, "Invalid arguments"),
12 (
13 "unsupported",
14 2,
15 "Requires Windows or WSL and Windows OneNote desktop",
16 ),
17 ("not_found", 4, "The requested resource is unavailable"),
18 (
19 "desktop_error",
20 5,
21 "OneNote or its PowerShell bridge failed",
22 ),
23 (
24 "conflict",
25 6,
26 "Page changed before the append; review before retrying",
27 ),
28 (
29 "write_uncertain",
30 7,
31 "Write outcome is uncertain; inspect OneNote before retrying",
32 ),
33 ("unexpected_error", 1, "Local input/output failure"),
34];
35
36impl Error {
37 pub fn new(kind: &'static str, message: impl Into<String>) -> Self {
38 Self {
39 kind,
40 message: message.into(),
41 page_id: None,
42 }
43 }
44 pub fn with_page(mut self, id: &str) -> Self {
45 self.page_id = Some(id.to_owned());
46 self
47 }
48 pub fn invalid(message: impl Into<String>) -> Self {
49 Self::new("invalid_input", message)
50 }
51 pub fn desktop(message: impl Into<String>) -> Self {
52 Self::new("desktop_error", message)
53 }
54 pub fn code(&self) -> i32 {
55 CONTRACTS
56 .iter()
57 .find(|c| c.0 == self.kind)
58 .map_or(1, |c| c.1)
59 }
60}
61impl fmt::Display for Error {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 f.write_str(&self.message)
64 }
65}
66impl std::error::Error for Error {}
67impl From<std::io::Error> for Error {
68 fn from(e: std::io::Error) -> Self {
69 Self::new("unexpected_error", e.to_string())
70 }
71}