about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-12-14 12:31:10 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-12-14 12:31:10 +0100
commitbeb56409e033fb6d89749788cbf0c91046e3fc16 (patch)
treee04ee90dab32b7465f0946a91ac0021a0ec97108
parentfeat(tree-sitter-yts): Update to new tree-sitter version & improve parsing (diff)
downloadyt-beb56409e033fb6d89749788cbf0c91046e3fc16.tar.gz
yt-beb56409e033fb6d89749788cbf0c91046e3fc16.zip
fix(yt/cli): Ensure that all `[No <xyz>]` value can be parsed
-rw-r--r--yt/src/cli.rs34
-rw-r--r--yt/src/select/selection_file/duration.rs15
2 files changed, 43 insertions, 6 deletions
diff --git a/yt/src/cli.rs b/yt/src/cli.rs
index 78d8de9..fe85a89 100644
--- a/yt/src/cli.rs
+++ b/yt/src/cli.rs
@@ -8,7 +8,7 @@
 // You should have received a copy of the License along with this program.
 // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
 
-use std::path::PathBuf;
+use std::{path::PathBuf, str::FromStr};
 
 use anyhow::Context;
 use bytes::Bytes;
@@ -216,14 +216,42 @@ pub struct SharedSelectionCommandArgs {
 
     pub title: String,
 
-    pub date: NaiveDate,
+    pub date: OptionalNaiveDate,
 
-    pub publisher: String,
+    pub publisher: OptionalPublisher,
 
     pub duration: Duration,
 
     pub url: Url,
 }
+#[derive(Clone, Debug, Copy)]
+pub struct OptionalNaiveDate {
+    pub date: Option<NaiveDate>,
+}
+impl FromStr for OptionalNaiveDate {
+    type Err = anyhow::Error;
+    fn from_str(v: &str) -> Result<Self,Self::Err> {
+        if v == "[No release date]" {
+        Ok(Self {date: None})
+        } else {
+        Ok(Self {date: Some(NaiveDate::from_str(v)?)})
+        }
+    }
+}
+#[derive(Clone, Debug)]
+pub struct OptionalPublisher {
+    pub publisher: Option<String>,
+}
+impl FromStr for OptionalPublisher {
+    type Err = anyhow::Error;
+    fn from_str(v: &str) -> Result<Self,Self::Err> {
+        if v == "[No author]" {
+        Ok(Self {publisher: None})
+        } else {
+        Ok(Self {publisher: Some(v.to_owned())})
+        }
+    }
+}
 
 #[derive(Subcommand, Clone, Debug)]
 // NOTE: Keep this in sync with the [`constants::HELP_STR`] constant. <2024-08-20>
diff --git a/yt/src/select/selection_file/duration.rs b/yt/src/select/selection_file/duration.rs
index 3957f0f..ab3a18b 100644
--- a/yt/src/select/selection_file/duration.rs
+++ b/yt/src/select/selection_file/duration.rs
@@ -14,7 +14,7 @@ use anyhow::{Context, Result};
 
 use crate::unreachable::Unreachable;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Duration {
     time: u32,
 }
@@ -30,7 +30,7 @@ impl FromStr for Duration {
                 .with_context(|| format!("Failed to parse '{suffix}'"))
         }
 
-        if s == "[No Duration]" {
+        if s == "[No duration]" {
             return Ok(Self { time: 0 });
         }
 
@@ -88,7 +88,7 @@ impl std::fmt::Display for Duration {
         let s = base_sec / SECOND;
 
         if self.time == 0 {
-            write!(f, "[No Duration]")
+            write!(f, "[No duration]")
         } else if h > 0 {
             write!(f, "{h}h {m}m")
         } else {
@@ -98,6 +98,8 @@ impl std::fmt::Display for Duration {
 }
 #[cfg(test)]
 mod test {
+    use std::str::FromStr;
+
     use super::Duration;
 
     #[test]
@@ -110,4 +112,11 @@ mod test {
         let dur = Duration { time: 60 * 30 };
         assert_eq!("30m 0s".to_owned(), dur.to_string());
     }
+    #[test]
+    fn test_display_duration_roundtrip() {
+        let dur = Duration { time: 0 };
+        let dur_str = dur.to_string();
+
+        assert_eq!(Duration { time: 0 }, Duration::from_str(&dur_str).unwrap());
+    }
 }