1use std::fmt;
4use std::path::PathBuf;
5
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[serde(rename_all = "lowercase")]
11pub enum SettingsScope {
12 Global,
14 Project,
16}
17
18impl fmt::Display for SettingsScope {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 f.write_str(match self {
21 Self::Global => "global",
22 Self::Project => "project",
23 })
24 }
25}
26
27#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
29#[non_exhaustive]
30pub enum SettingsErrorKind {
31 #[error("{0}")]
33 Read(String),
34 #[error("{0}")]
36 Parse(String),
37 #[error("settings must be a JSON object")]
39 NotAnObject,
40 #[error("failed to lock settings: {0}")]
42 Lock(String),
43 #[error("{0}")]
45 Write(String),
46 #[error("Project is not trusted; refusing to write project settings")]
48 ProjectUntrusted,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
54pub struct SettingsError {
55 pub scope: SettingsScope,
57 pub path: Option<PathBuf>,
59 pub kind: SettingsErrorKind,
61}
62
63impl SettingsError {
64 #[must_use]
66 pub fn message(&self) -> String {
67 self.kind.to_string()
68 }
69}
70
71impl fmt::Display for SettingsError {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 match &self.path {
75 Some(path) => write!(f, "Invalid settings file {}: {}", path.display(), self.kind),
76 None => write!(f, "Invalid {} settings: {}", self.scope, self.kind),
77 }
78 }
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
83#[error("{message}")]
84pub struct InvalidSettingError {
85 pub message: String,
87}
88
89impl InvalidSettingError {
90 pub(crate) fn new(message: impl Into<String>) -> Self {
91 Self {
92 message: message.into(),
93 }
94 }
95}