1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Typed error surface for the `org-gdocs` library.
//!
//! Every distinct failure a caller might branch on is its own variant. `anyhow`
//! is confined to the binary edge and never appears here.
use std::path::PathBuf;
/// Errors raised by `org-gdocs` library code.
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// A filesystem operation failed for the given path.
#[error("I/O error at {path}: {source}")]
Io {
/// Path the failing operation targeted.
path: PathBuf,
/// Underlying I/O error.
source: std::io::Error,
},
/// The configuration file could not be parsed as TOML.
#[error("invalid TOML configuration: {0}")]
ConfigToml(#[from] toml::de::Error),
/// The configuration could not be serialized to TOML.
#[error("could not serialize TOML configuration: {0}")]
ConfigTomlSerialize(#[from] toml::ser::Error),
/// A JSON value could not be (de)serialized.
///
/// JSON is confined to the forced external boundaries (the Google API wire
/// format and OAuth credential/token files, OVR-1/A5); surfaces this crate
/// owns use s-expressions and surface [`Error::Sexp`] instead.
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
/// An s-expression (the `** Sync State` block or the CLI↔Emacs envelope, A5)
/// could not be parsed or did not match the expected shape.
#[error("s-expression error: {0}")]
Sexp(#[from] crate::sexp::SexpError),
/// A Google Docs or Drive API call failed — transport, protocol, or a
/// non-success API response.
///
/// The generated client's error type is mapped to its display string at the
/// single seam in [`crate::google::client`] (F6) so it never leaks into this
/// crate's public surface (EI-1).
#[error("Google API error: {0}")]
Google(String),
/// The target document exposes more than one tab, which is unsupported.
///
/// We operate only on the first/legacy tab (DI-6); a multi-tab document is
/// reported rather than silently mis-indexed.
#[error("document has multiple tabs, which is unsupported (operate on a single-tab document)")]
MultipleTabs,
/// The org body could not be parsed by `tftio-kb`.
#[error("could not parse org body: {0}")]
OrgParse(String),
/// The org file has no linked Google Doc (`#+GDOC_ID:`).
///
/// `pull`, `clean`, and `open` all require a document to have been created by
/// a prior `push`; this is the branchable failure they surface when it has not.
#[error("org file has no linked Google Doc (#+GDOC_ID:); run `push` first")]
NotLinked,
/// A required path could not be resolved (e.g. no home/config directory).
#[error("could not resolve {0}")]
PathResolution(String),
/// OAuth authentication, token acquisition, or TLS setup failed.
#[error("authentication error: {0}")]
Auth(String),
}
/// Convenience result alias for fallible `org-gdocs` library functions.
pub type Result<T> = std::result::Result<T, Error>;