Skip to content

Commit 3dd061c

Browse files
committed
fix(config): Fix error formatting
1 parent 6f7b50e commit 3dd061c

File tree

1 file changed

+103
-42
lines changed

1 file changed

+103
-42
lines changed

src/models.rs

+103-42
Original file line numberDiff line numberDiff line change
@@ -1137,54 +1137,115 @@ impl Validate for SettingData {
11371137
}
11381138

11391139
#[derive(Debug, Error)]
1140-
pub enum SettingError {
1141-
#[error("error processing JSON: {0}")]
1140+
pub enum SettingErrorKind {
1141+
#[error(transparent)]
11421142
Serde(#[from] serde_json::Error),
1143-
#[error("error parsing date: {0}")]
1143+
#[error("error parsing date")]
11441144
Chrono(#[from] chrono::ParseError),
1145-
#[error("validation error: {0}")]
1145+
#[error(transparent)]
11461146
Validation(#[from] validator::ValidationErrors),
1147+
#[error("unknown setting type")]
1148+
UnknownType,
1149+
}
1150+
1151+
#[derive(Debug)]
1152+
pub struct SettingError {
1153+
pub kind: SettingErrorKind,
1154+
pub setting: &'static str,
1155+
unknown: Option<String>,
1156+
}
1157+
1158+
impl SettingError {
1159+
pub fn new(kind: impl Into<SettingErrorKind>, setting: &'static str) -> Self {
1160+
Self {
1161+
kind: kind.into(),
1162+
setting,
1163+
unknown: None,
1164+
}
1165+
}
1166+
1167+
pub fn unknown(name: &str) -> Self {
1168+
Self {
1169+
kind: SettingErrorKind::UnknownType,
1170+
setting: "",
1171+
unknown: Some(name.to_owned()),
1172+
}
1173+
}
1174+
}
1175+
1176+
impl std::error::Error for SettingError {
1177+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1178+
self.kind.source()
1179+
}
1180+
}
1181+
1182+
impl std::fmt::Display for SettingError {
1183+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1184+
match &self.unknown {
1185+
Some(setting) => write!(f, "`{}`: {}", setting, self.kind),
1186+
None => write!(f, "`{}`: {}", self.setting, self.kind),
1187+
}
1188+
}
1189+
}
1190+
1191+
macro_rules! convert_settings {
1192+
($db:ident, $($name:literal => $variant:ident),*) => {
1193+
match $db.ty.as_str() {
1194+
$($name => {
1195+
let config = SettingData::$variant(serde_json::from_str(&$db.config).map_err(|err| {
1196+
SettingError::new(err, $name)
1197+
})?);
1198+
1199+
(
1200+
match config.validate() {
1201+
Ok(_) => Ok(config),
1202+
Err(err) => Err(SettingError::new(err, $name)),
1203+
}?,
1204+
chrono::DateTime::parse_from_rfc3339(&$db.updated_at).map_err(|err| {
1205+
SettingError::new(err, $name)
1206+
})?.with_timezone(&chrono::Utc)
1207+
)
1208+
},)*
1209+
other => {
1210+
return Err(SettingError::unknown(other));
1211+
}
1212+
}
1213+
};
11471214
}
11481215

11491216
impl TryFrom<db_models::DbSetting> for Setting {
11501217
type Error = SettingError;
11511218

11521219
fn try_from(db: db_models::DbSetting) -> Result<Self, Self::Error> {
1153-
let config = match db.ty.as_str() {
1154-
"backgroundEffect" => SettingData::BackgroundEffect(serde_json::from_str(&db.config)?),
1155-
"blackborderdetector" => {
1156-
SettingData::BlackBorderDetector(serde_json::from_str(&db.config)?)
1157-
}
1158-
"boblightServer" => SettingData::BoblightServer(serde_json::from_str(&db.config)?),
1159-
"color" => SettingData::ColorAdjustment(serde_json::from_str(&db.config)?),
1160-
"device" => SettingData::Device(serde_json::from_str(&db.config)?),
1161-
"effects" => SettingData::Effects(serde_json::from_str(&db.config)?),
1162-
"flatbufServer" => SettingData::FlatbuffersServer(serde_json::from_str(&db.config)?),
1163-
"foregroundEffect" => SettingData::ForegroundEffect(serde_json::from_str(&db.config)?),
1164-
"forwarder" => SettingData::Forwarder(serde_json::from_str(&db.config)?),
1165-
"framegrabber" => SettingData::Framegrabber(serde_json::from_str(&db.config)?),
1166-
"general" => SettingData::General(serde_json::from_str(&db.config)?),
1167-
"grabberV4L2" => SettingData::GrabberV4L2(serde_json::from_str(&db.config)?),
1168-
"instCapture" => SettingData::InstanceCapture(serde_json::from_str(&db.config)?),
1169-
"jsonServer" => SettingData::JsonServer(serde_json::from_str(&db.config)?),
1170-
"ledConfig" => SettingData::LedConfig(serde_json::from_str(&db.config)?),
1171-
"leds" => SettingData::Leds(serde_json::from_str(&db.config)?),
1172-
"logger" => SettingData::Logger(serde_json::from_str(&db.config)?),
1173-
"network" => SettingData::Network(serde_json::from_str(&db.config)?),
1174-
"protoServer" => SettingData::ProtoServer(serde_json::from_str(&db.config)?),
1175-
"smoothing" => SettingData::Smoothing(serde_json::from_str(&db.config)?),
1176-
"webConfig" => SettingData::WebConfig(serde_json::from_str(&db.config)?),
1177-
"hooks" => SettingData::Hooks(serde_json::from_str(&db.config)?),
1178-
other => panic!("unsupported setting type: {}", other),
1179-
};
1180-
1181-
config.validate()?;
1220+
let (config, updated_at) = convert_settings!(db,
1221+
"backgroundEffect" => BackgroundEffect,
1222+
"blackborderdetector" => BlackBorderDetector,
1223+
"boblightServer" => BoblightServer,
1224+
"color" => ColorAdjustment,
1225+
"device" => Device,
1226+
"effects" => Effects,
1227+
"flatbufServer" => FlatbuffersServer,
1228+
"foregroundEffect" => ForegroundEffect,
1229+
"forwarder" => Forwarder,
1230+
"framegrabber" => Framegrabber,
1231+
"general" => General,
1232+
"grabberV4L2" => GrabberV4L2,
1233+
"instCapture" => InstanceCapture,
1234+
"jsonServer" => JsonServer,
1235+
"ledConfig" => LedConfig,
1236+
"leds" => Leds,
1237+
"logger" => Logger,
1238+
"network" => Network,
1239+
"protoServer" => ProtoServer,
1240+
"smoothing" => Smoothing,
1241+
"webConfig" => WebConfig,
1242+
"hooks" => Hooks
1243+
);
11821244

11831245
Ok(Self {
11841246
hyperion_inst: db.hyperion_inst,
11851247
config,
1186-
updated_at: chrono::DateTime::parse_from_rfc3339(&db.updated_at)?
1187-
.with_timezone(&chrono::Utc),
1248+
updated_at,
11881249
})
11891250
}
11901251
}
@@ -1497,21 +1558,21 @@ impl InstanceConfigCreator {
14971558

14981559
#[derive(Debug, Error)]
14991560
pub enum ConfigError {
1500-
#[error("i/o error: {0}")]
1561+
#[error("i/o error")]
15011562
Io(#[from] std::io::Error),
1502-
#[error("error querying the database: {0}")]
1563+
#[error("error querying the database")]
15031564
Sqlx(#[from] sqlx::Error),
1504-
#[error("error loading instance: {0}")]
1565+
#[error("error loading instance")]
15051566
Instance(#[from] InstanceError),
1506-
#[error("error loading setting: {0}")]
1567+
#[error("error loading setting")]
15071568
Setting(#[from] SettingError),
1508-
#[error("error loading meta: {0}")]
1569+
#[error("error loading meta")]
15091570
Meta(#[from] MetaError),
1510-
#[error("error loading user: {0}")]
1571+
#[error("error loading user")]
15111572
User(#[from] UserError),
15121573
#[error("missing hyperion_inst field on instance setting {0}")]
15131574
MissingHyperionInst(&'static str),
1514-
#[error("invalid TOML: {0}")]
1575+
#[error("invalid TOML")]
15151576
Toml(#[from] toml::de::Error),
15161577
#[error("instance id must be an integer, got {0}")]
15171578
InvalidId(String),

0 commit comments

Comments
 (0)