Skip to content

Commit

Permalink
Dynamically sized article lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
zargony committed Jan 19, 2025
1 parent 0f5fd88 commit 68b2005
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 34 deletions.
38 changes: 17 additions & 21 deletions firmware/src/article.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;

/// Article id
/// Equivalent to the Vereinsflieger `articleid` attribute
Expand All @@ -18,52 +20,46 @@ pub struct Article {
/// list of article ids is given on initialization (from static system configuration), while
/// article information is fetched later from Vereinsflieger.
#[derive(Debug)]
pub struct Articles<const N: usize> {
ids: [ArticleId; N],
articles: [Option<Article>; N],
pub struct Articles {
/// Look up index to article id
ids: Vec<ArticleId>,
/// Look up article id to article information
articles: BTreeMap<ArticleId, Article>,
}

impl<const N: usize> Articles<N> {
impl Articles {
/// Create new article lookup table
pub fn new(ids: [ArticleId; N]) -> Self {
pub fn new(ids: Vec<ArticleId>) -> Self {
Self {
ids,
articles: [const { None }; N],
articles: BTreeMap::new(),
}
}

/// Clear all article information
pub fn clear(&mut self) {
self.articles = [const { None }; N];
self.articles.clear();
}

/// Update article with given article id. Ignores article ids not in list.
pub fn update(&mut self, id: &ArticleId, name: String, price: f32) {
if let Some(idx) = self.find(id) {
self.articles[idx] = Some(Article { name, price });
if self.ids.contains(id) {
self.articles.insert(id.clone(), Article { name, price });
}
}

/// Number of articles
pub fn count(&self) -> usize {
self.articles.iter().filter(|a| a.is_some()).count()
}

/// Find index of article with given id
pub fn find(&self, id: &ArticleId) -> Option<usize> {
self.ids.iter().position(|i| i == id)
self.articles.len()
}

/// Look up id of article at given index
pub fn id(&self, index: usize) -> Option<&ArticleId> {
self.ids.get(index)
}

/// Look up article information at given index
pub fn get(&self, index: usize) -> Option<&Article> {
match self.articles.get(index) {
Some(Some(article)) => Some(article),
_ => None,
}
/// Look up article by article id
pub fn get(&self, id: &ArticleId) -> Option<&Article> {
self.articles.get(id)
}
}
2 changes: 1 addition & 1 deletion firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ async fn main(spawner: Spawner) {
let config = config::Config::read().await;

// Initialize article and user look up tables
let mut articles = article::Articles::new([config.vf_article_ids[0].clone()]);
let mut articles = article::Articles::new(config.vf_article_ids);
let mut users = user::Users::new();

// Initialize I2C controller
Expand Down
9 changes: 6 additions & 3 deletions firmware/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub struct Ui<'a, RNG, I2C, IRQ> {
wifi: &'a Wifi,
http: &'a mut Http<'a>,
vereinsflieger: &'a mut Vereinsflieger<'a>,
articles: &'a mut Articles<1>,
articles: &'a mut Articles,
users: &'a mut Users,
telemetry: &'a mut Telemetry<'a>,
schedule: &'a mut Daily,
Expand All @@ -66,7 +66,7 @@ impl<'a, RNG: RngCore, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, RNG, I2C,
wifi: &'a Wifi,
http: &'a mut Http<'a>,
vereinsflieger: &'a mut Vereinsflieger<'a>,
articles: &'a mut Articles<1>,
articles: &'a mut Articles,
users: &'a mut Users,
telemetry: &'a mut Telemetry<'a>,
schedule: &'a mut Daily,
Expand Down Expand Up @@ -261,7 +261,10 @@ impl<'a, RNG: RngCore, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, RNG, I2C,
.id(0)
.ok_or(ErrorKind::ArticleNotFound)?
.clone();
let article = self.articles.get(0).ok_or(ErrorKind::ArticleNotFound)?;
let article = self
.articles
.get(&article_id)
.ok_or(ErrorKind::ArticleNotFound)?;

// Calculate total price. It's ok to cast num_drinks to f32 as it's always a small number.
#[allow(clippy::cast_precision_loss)]
Expand Down
2 changes: 1 addition & 1 deletion firmware/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct User {
pub struct Users {
/// Look up NFC uid to user id
uids: BTreeMap<Uid, UserId>,
/// Look up user id to user details
/// Look up user id to user information
users: BTreeMap<UserId, User>,
}

Expand Down
7 changes: 2 additions & 5 deletions firmware/src/vereinsflieger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,7 @@ impl Connection<'_> {
}

/// Fetch list of articles and update article lookup table
pub async fn refresh_articles<const N: usize>(
&mut self,
articles: &mut Articles<N>,
) -> Result<(), Error> {
pub async fn refresh_articles(&mut self, articles: &mut Articles) -> Result<(), Error> {
use proto_articles::{ArticleListRequest, ArticleListResponse};

debug!("Vereinsflieger: Refreshing articles...");
Expand All @@ -172,7 +169,7 @@ impl Connection<'_> {
articles.clear();
let articles = RefCell::new(articles);

let response: ArticleListResponse<N> =
let response: ArticleListResponse =
with_timeout(FETCH_TIMEOUT, json.read_object_with_context(&articles))
.await?
.map_err(http::Error::MalformedResponse)
Expand Down
6 changes: 3 additions & 3 deletions firmware/src/vereinsflieger/proto_articles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ impl ToJson for ArticleListRequest<'_> {

/// `articles/list` response
#[derive(Debug, Default)]
pub struct ArticleListResponse<const N: usize> {
pub struct ArticleListResponse {
// pub *: Article,
// pub httpstatuscode: u16,
//
/// Total number of articles
pub total_articles: u32,
}

impl<const N: usize> FromJsonObject for ArticleListResponse<N> {
impl FromJsonObject for ArticleListResponse {
// Mutable reference to article lookup table
type Context<'ctx> = RefCell<&'ctx mut Articles<N>>;
type Context<'ctx> = RefCell<&'ctx mut Articles>;

async fn read_next<R: BufRead>(
&mut self,
Expand Down

0 comments on commit 68b2005

Please sign in to comment.