1use std::{
9 fmt::{self, Display},
10 str::FromStr,
11};
12
13use crate::error::PaperClientError;
14
15#[derive(Debug, Clone, Copy, PartialEq)]
16pub enum PaperPolicy {
17 Auto,
18 Lfu,
19 Fifo,
20 Clock,
21 Sieve,
22 Lru,
23 Mru,
24 TwoQ(f64, f64),
25 Arc,
26 SThreeFifo(f64),
27}
28
29impl Display for PaperPolicy {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 PaperPolicy::Auto => write!(f, "auto"),
33 PaperPolicy::Lfu => write!(f, "lfu"),
34 PaperPolicy::Fifo => write!(f, "fifo"),
35 PaperPolicy::Clock => write!(f, "clock"),
36 PaperPolicy::Sieve => write!(f, "sieve"),
37 PaperPolicy::Lru => write!(f, "lru"),
38 PaperPolicy::Mru => write!(f, "mru"),
39 PaperPolicy::TwoQ(k_in, k_out) => write!(f, "2q-{k_in}-{k_out}"),
40 PaperPolicy::Arc => write!(f, "arc"),
41 PaperPolicy::SThreeFifo(ratio) => write!(f, "s3-fifo-{ratio}"),
42 }
43 }
44}
45
46impl FromStr for PaperPolicy {
47 type Err = PaperClientError;
48
49 fn from_str(value: &str) -> Result<Self, Self::Err> {
50 let policy = match value {
51 "auto" => PaperPolicy::Auto,
52 "lfu" => PaperPolicy::Lfu,
53 "fifo" => PaperPolicy::Fifo,
54 "clock" => PaperPolicy::Clock,
55 "sieve" => PaperPolicy::Sieve,
56 "lru" => PaperPolicy::Lru,
57 "mru" => PaperPolicy::Mru,
58 value if value.starts_with("2q-") => parse_two_q(value)?,
59 "arc" => PaperPolicy::Arc,
60 value if value.starts_with("s3-fifo-") => parse_s_three_fifo(value)?,
61
62 _ => return Err(PaperClientError::Internal),
63 };
64
65 Ok(policy)
66 }
67}
68
69fn parse_two_q(value: &str) -> Result<PaperPolicy, PaperClientError> {
70 let tokens = value[3..].split('-').collect::<Vec<&str>>();
72
73 if tokens.len() != 2 {
74 return Err(PaperClientError::Internal);
75 }
76
77 let Ok(k_in) = tokens[0].parse::<f64>() else {
78 return Err(PaperClientError::Internal);
79 };
80
81 let Ok(k_out) = tokens[1].parse::<f64>() else {
82 return Err(PaperClientError::Internal);
83 };
84
85 Ok(PaperPolicy::TwoQ(k_in, k_out))
86}
87
88fn parse_s_three_fifo(value: &str) -> Result<PaperPolicy, PaperClientError> {
89 let tokens = value[8..].split('-').collect::<Vec<&str>>();
91
92 if tokens.len() != 1 {
93 return Err(PaperClientError::Internal);
94 }
95
96 let Ok(ratio) = tokens[0].parse::<f64>() else {
97 return Err(PaperClientError::Internal);
98 };
99
100 Ok(PaperPolicy::SThreeFifo(ratio))
101}