Skip to main content

mii_memory/
model.rs

1use std::fmt;
2use std::str::FromStr;
3
4use anyhow::{anyhow, bail};
5use clap::ValueEnum;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ValueEnum)]
9#[serde(rename_all = "snake_case")]
10#[value(rename_all = "snake_case")]
11pub enum MemoryMode {
12    #[default]
13    Global,
14    Workspace,
15    Session,
16}
17
18impl MemoryMode {
19    pub fn as_str(self) -> &'static str {
20        match self {
21            Self::Global => "global",
22            Self::Workspace => "workspace",
23            Self::Session => "session",
24        }
25    }
26}
27
28impl fmt::Display for MemoryMode {
29    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30        formatter.write_str(self.as_str())
31    }
32}
33
34impl FromStr for MemoryMode {
35    type Err = anyhow::Error;
36
37    fn from_str(value: &str) -> Result<Self, Self::Err> {
38        match value.trim().to_ascii_lowercase().as_str() {
39            "global" => Ok(Self::Global),
40            "workspace" => Ok(Self::Workspace),
41            "session" => Ok(Self::Session),
42            other => bail!("unsupported memory mode: {other}"),
43        }
44    }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ValueEnum)]
48#[serde(rename_all = "snake_case")]
49#[value(rename_all = "snake_case")]
50pub enum ExpirationCondition {
51    Time,
52    Usage,
53    FileExist,
54    FilePristine,
55    Period,
56}
57
58impl ExpirationCondition {
59    pub fn as_str(self) -> &'static str {
60        match self {
61            Self::Time => "time",
62            Self::Usage => "usage",
63            Self::FileExist => "file_exist",
64            Self::FilePristine => "file_pristine",
65            Self::Period => "period",
66        }
67    }
68}
69
70impl fmt::Display for ExpirationCondition {
71    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
72        formatter.write_str(self.as_str())
73    }
74}
75
76impl FromStr for ExpirationCondition {
77    type Err = anyhow::Error;
78
79    fn from_str(value: &str) -> Result<Self, Self::Err> {
80        match value.trim().to_ascii_lowercase().as_str() {
81            "time" => Ok(Self::Time),
82            "usage" => Ok(Self::Usage),
83            "file_exist" | "file-exist" => Ok(Self::FileExist),
84            "file_pristine" | "file-pristine" => Ok(Self::FilePristine),
85            "period" => Ok(Self::Period),
86            other => Err(anyhow!("unsupported expiration condition: {other}")),
87        }
88    }
89}
90
91pub fn normalize_tags(tags: &[String]) -> Vec<String> {
92    let mut normalized = Vec::new();
93
94    for tag in tags {
95        let tag = tag.trim().to_ascii_lowercase();
96        if tag.is_empty() || normalized.contains(&tag) {
97            continue;
98        }
99        normalized.push(tag);
100    }
101
102    normalized
103}