Skip to content

Commit

Permalink
rust: handle invalid pattern selection reasons
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Mar 5, 2024
1 parent 7cbe2b7 commit 4c0cb3b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 15 deletions.
2 changes: 1 addition & 1 deletion rust/agama-lib/src/software.rs
Expand Up @@ -5,6 +5,6 @@ pub mod proxies;
mod settings;
mod store;

pub use client::{Pattern, SelectedBy, SoftwareClient};
pub use client::{Pattern, SelectedBy, SoftwareClient, UnknownSelectedBy};
pub use settings::SoftwareSettings;
pub use store::SoftwareStore;
36 changes: 27 additions & 9 deletions rust/agama-lib/src/software/client.rs
Expand Up @@ -22,7 +22,7 @@ pub struct Pattern {
}

/// Represents the reason why a pattern is selected.
#[derive(Clone, Copy, Debug, Serialize)]
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
pub enum SelectedBy {
/// The pattern was selected by the user.
User = 0,
Expand All @@ -32,12 +32,18 @@ pub enum SelectedBy {
None = 2,
}

impl From<u8> for SelectedBy {
fn from(value: u8) -> Self {
#[derive(Debug, thiserror::Error)]
#[error("Unknown selected by value: '{0}'")]
pub struct UnknownSelectedBy(u8);

impl TryFrom<u8> for SelectedBy {
type Error = UnknownSelectedBy;

fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Self::User,
1 => Self::Auto,
_ => Self::None,
0 => Ok(Self::User),
1 => Ok(Self::Auto),
_ => Err(UnknownSelectedBy(value)),
}
}
}
Expand Down Expand Up @@ -83,8 +89,14 @@ impl<'a> SoftwareClient<'a> {
.selected_patterns()
.await?
.into_iter()
.filter(|(_id, reason)| *reason == SelectedBy::User as u8)
.map(|(id, _reason)| id)
.filter_map(|(id, reason)| match SelectedBy::try_from(reason) {
Ok(reason) if reason == SelectedBy::User => Some(id),
Ok(_reason) => None,
Err(e) => {
log::warn!("Ignoring pattern {}. Error: {}", &id, e);
None
}
})
.collect();
Ok(patterns)
}
Expand All @@ -94,7 +106,13 @@ impl<'a> SoftwareClient<'a> {
let patterns = self.software_proxy.selected_patterns().await?;
let patterns = patterns
.into_iter()
.map(|(id, reason)| (id, reason.into()))
.filter_map(|(id, reason)| match SelectedBy::try_from(reason) {
Ok(reason) => Some((id, reason)),
Err(e) => {
log::warn!("Ignoring pattern {}. Error: {}", &id, e);
None
}
})
.collect();
Ok(patterns)
}
Expand Down
28 changes: 23 additions & 5 deletions rust/agama-server/src/software/web.rs
Expand Up @@ -11,7 +11,7 @@ use agama_lib::{
product::{Product, ProductClient},
software::{
proxies::{Software1Proxy, SoftwareProductProxy},
Pattern, SelectedBy, SoftwareClient,
Pattern, SelectedBy, SoftwareClient, UnknownSelectedBy,
},
};
use axum::{
Expand Down Expand Up @@ -90,16 +90,34 @@ async fn patterns_changed_stream(
.await
.then(|change| async move {
if let Ok(patterns) = change.get().await {
let patterns: HashMap<String, SelectedBy> =
patterns.into_iter().map(|(k, v)| (k, v.into())).collect();
return Some(Event::PatternsChanged(patterns));
return match reason_to_selected_by(patterns) {
Ok(patterns) => Some(patterns),
Err(error) => {
log::warn!("Ignoring the list of changed patterns. Error: {}", error);
None
}
};
}
None
})
.filter_map(|e| e);
.filter_map(|e| e.map(Event::PatternsChanged));
Ok(stream)
}

// Returns a hash replacing the selection "reason" from D-Bus with a SelectedBy variant.
fn reason_to_selected_by(
patterns: HashMap<String, u8>,
) -> Result<HashMap<String, SelectedBy>, UnknownSelectedBy> {
let mut selected: HashMap<String, SelectedBy> = HashMap::new();
for (id, reason) in patterns {
match SelectedBy::try_from(reason) {
Ok(selected_by) => selected.insert(id, selected_by),
Err(e) => return Err(e),
};
}
Ok(selected)
}

/// Sets up and returns the axum service for the software module.
pub async fn software_service(dbus: zbus::Connection) -> Result<Router, ServiceError> {
let product = ProductClient::new(dbus.clone()).await?;
Expand Down

0 comments on commit 4c0cb3b

Please sign in to comment.