Skip to main content

wechat_profile/
lib.rs

1//! Readers and narrow opt-in writers for selected official Linux profiles.
2//!
3//! Offline readers use a private temporary copy, including its WAL, without
4//! changing source SHM. An owned daemon can instead reuse read-only connections
5//! while serializing profile operations. This crate neither launches WeChat nor connects
6//! to the network or acquires keys from a process. Checked write functions require
7//! explicit ownership and a durable caller intent.
8mod dat;
9mod images;
10mod initialize;
11mod keys;
12mod login_storage;
13mod media;
14mod mmkv;
15mod model;
16mod owned_reader;
17mod peer_metadata;
18mod projection;
19mod reader;
20mod recall_search;
21mod recalls;
22mod schema;
23mod snapshot;
24mod thread_read;
25mod writer;
26
27pub use dat::*;
28pub use initialize::*;
29pub use keys::*;
30pub use login_storage::*;
31pub use media::*;
32pub use mmkv::*;
33pub use model::*;
34pub use owned_reader::OwnedReaderCache;
35pub use peer_metadata::*;
36pub use projection::*;
37pub use reader::*;
38pub use recall_search::*;
39pub use recalls::*;
40pub use schema::*;
41pub use snapshot::{keys_from_agent_cache, keys_from_password, ProfileLocation, ReadOptions};
42pub use thread_read::*;
43pub use writer::*;
44
45#[derive(Debug, thiserror::Error)]
46pub enum ProfileError {
47    #[error("profile source is unavailable or not an account root")]
48    InvalidProfile,
49    #[error("a stopped profile or consistent snapshot must be explicitly confirmed")]
50    SnapshotRequired,
51    #[error("parallel snapshots are unavailable for this profile layout")]
52    ParallelSnapshotUnavailable,
53    #[error("profile changed while the read snapshot was being copied")]
54    SourceChanged,
55    #[error("source contains an unsupported link or special file")]
56    UnsupportedFile,
57    #[error("profile resource exceeds a configured bound")]
58    ResourceLimit,
59    #[error("protected keys file is missing")]
60    KeysMissing,
61    #[error("keys file must be a private regular file")]
62    InsecureKeysFile,
63    #[error("invalid or unsupported keys file")]
64    InvalidKeysFile,
65    #[error("keys are bound to a different account directory")]
66    AccountMismatch,
67    #[error("no authorized key is available for database {0}")]
68    KeyUnavailable(String),
69    #[error("supplied key or database generation did not validate for {0}")]
70    KeyMismatch(String),
71    #[error("validated database could not be opened for {0}")]
72    DatabaseOpen(String),
73    #[error("the database engine does not provide SQLCipher support")]
74    SqlcipherUnavailable,
75    #[error("unsupported database schema for {0}")]
76    UnsupportedSchema(String),
77    #[error("official-profile writes are not supported by this adapter")]
78    WritesUnsupported,
79    #[error("invalid or query-mismatched continuation cursor")]
80    InvalidCursor,
81    #[error("continuation source generation changed; start a new query")]
82    CursorExpired,
83    #[error("invalid query or identifier")]
84    InvalidQuery,
85    #[error("requested bytes are not cached")]
86    NotCached,
87    #[error("requested local image quality is not established by this adapter")]
88    ImageQualityUnavailable,
89    #[error("local image key is unavailable")]
90    ImageKeyUnavailable,
91    #[error("invalid or unsupported local V2 DAT payload")]
92    InvalidDat,
93    #[error("corrupt or unsupported encoded metadata")]
94    InvalidMetadata,
95    #[error("profile filesystem operation failed")]
96    Io(#[from] std::io::Error),
97    // Do not expose SQLCipher error SQL/parameters or row content to callers.
98    #[error("profile database operation failed")]
99    Database,
100}
101
102impl From<rusqlite::Error> for ProfileError {
103    fn from(_: rusqlite::Error) -> Self {
104        Self::Database
105    }
106}
107
108pub type Result<T> = std::result::Result<T, ProfileError>;