From 61b3a92792c78113fd4429bcda2cb71c5381f0ca Mon Sep 17 00:00:00 2001 From: William Casarin Date: Sun, 5 Jan 2025 10:57:37 -0600 Subject: [PATCH] token_parser: unify parsing and serialization This reduces the number of things we have to update in our token parser and serializer. For payloads, we we have to handle the payload cases different, but we now have a structure that can deal with that efficiently. Signed-off-by: William Casarin --- .../src/storage/token_parser.rs | 1 + crates/notedeck_columns/src/ui/add_column.rs | 90 ++++++++++--------- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/crates/notedeck_columns/src/storage/token_parser.rs b/crates/notedeck_columns/src/storage/token_parser.rs index a1d49f26..45b43595 100644 --- a/crates/notedeck_columns/src/storage/token_parser.rs +++ b/crates/notedeck_columns/src/storage/token_parser.rs @@ -146,6 +146,7 @@ pub trait TokenSerializable: Sized { /// Return a list of serialization plans for a type. We do this for /// type safety and assume constructing these types are lightweight fn parse<'a>(parser: &mut TokenParser<'a>) -> Result>; + fn serialize(&self, write_token: fn(&str) -> Result<(), std::io::Error>) -> Result<(), std::io::Error>; } #[cfg(test)] diff --git a/crates/notedeck_columns/src/ui/add_column.rs b/crates/notedeck_columns/src/ui/add_column.rs index 80a4d16a..0ee4ffba 100644 --- a/crates/notedeck_columns/src/ui/add_column.rs +++ b/crates/notedeck_columns/src/ui/add_column.rs @@ -80,7 +80,47 @@ pub enum AddColumnRoute { ExternalIndividual, } +// Parser for the common case without any payloads +fn parse_column_route<'a>( + parser: &mut TokenParser<'a>, + route: AddColumnRoute, +) -> Result> { + parser.parse_all(|p| { + for token in route.tokens() { + p.parse_token(token)?; + } + Ok(route) + }) +} + +impl AddColumnRoute { + /// Route tokens use in both serialization and deserialization + fn tokens(&self) -> &'static [&'static str] { + match self { + Self::Base => &[], + Self::UndecidedNotification => &["notification_selection"], + Self::ExternalNotification => &["external_notif_selection"], + Self::UndecidedIndividual => &["individual_selection"], + Self::ExternalIndividual => &["external_individual_selection"], + Self::Hashtag => &["hashtag"], + Self::Algo(AddAlgoRoute::Base) => &["algo_selection"], + Self::Algo(AddAlgoRoute::LastPerPubkey) => &["algo_selection", "last_per_pubkey"], + // NOTE!!! When adding to this, update the parser for TokenSerializable below + } + } +} + impl TokenSerializable for AddColumnRoute { + fn serialize( + &self, + write_token: fn(&str) -> Result<(), std::io::Error>, + ) -> Result<(), std::io::Error> { + for token in self.tokens() { + write_token(token)?; + } + Ok(()) + } + fn parse<'a>(parser: &mut TokenParser<'a>) -> Result> { // all start with column parser.parse_token("column")?; @@ -93,49 +133,13 @@ impl TokenSerializable for AddColumnRoute { TokenParser::alt( parser, &[ - |p| { - p.parse_all(|p| { - p.parse_token("external_notif_selection")?; - Ok(AddColumnRoute::UndecidedNotification) - }) - }, - |p| { - p.parse_all(|p| { - p.parse_token("external_notif_selection")?; - Ok(AddColumnRoute::ExternalNotification) - }) - }, - |p| { - p.parse_all(|p| { - p.parse_token("hashtag_selection")?; - Ok(AddColumnRoute::Hashtag) - }) - }, - |p| { - p.parse_all(|p| { - p.parse_token("algo_selection")?; - Ok(AddColumnRoute::Algo(AddAlgoRoute::Base)) - }) - }, - |p| { - p.parse_all(|p| { - p.parse_token("algo_selection")?; - p.parse_token("last_per_pubkey")?; - Ok(AddColumnRoute::Algo(AddAlgoRoute::LastPerPubkey)) - }) - }, - |p| { - p.parse_all(|p| { - p.parse_token("individual_selection")?; - Ok(AddColumnRoute::UndecidedIndividual) - }) - }, - |p| { - p.parse_all(|p| { - p.parse_token("external_individual_selection")?; - Ok(AddColumnRoute::ExternalIndividual) - }) - }, + |p| parse_column_route(p, AddColumnRoute::UndecidedNotification), + |p| parse_column_route(p, AddColumnRoute::ExternalNotification), + |p| parse_column_route(p, AddColumnRoute::UndecidedIndividual), + |p| parse_column_route(p, AddColumnRoute::ExternalIndividual), + |p| parse_column_route(p, AddColumnRoute::Hashtag), + |p| parse_column_route(p, AddColumnRoute::Algo(AddAlgoRoute::Base)), + |p| parse_column_route(p, AddColumnRoute::Algo(AddAlgoRoute::LastPerPubkey)), ], ) }