1use moon_common::cacheable;
2use std::ops::Deref;
3
4cacheable!(
5 #[derive(Clone, Debug, Eq, PartialEq)]
6 #[serde(into = "String", from = "String")]
7 pub struct TaskArg {
8 pub quoted_value: Option<String>,
10
11 pub value: String, }
14);
15
16impl TaskArg {
17 pub fn new(base_value: impl AsRef<str>) -> Self {
18 let base_value = base_value.as_ref();
19 let mut is_quoted = false;
20 let mut quoted_value = None;
21 let mut value = String::new();
22
23 for (start, end) in [
25 ("\"", "\""),
26 ("'", "'"),
27 ("$\"", "\""),
28 ("$'", "'"),
29 ("%(", ")"),
30 ("r#'", "'#"),
31 ] {
32 if base_value.starts_with(start) && base_value.ends_with(end) {
33 value.push_str(base_value.trim_start_matches(start).trim_end_matches(end));
34 quoted_value = Some(base_value.to_owned());
35 is_quoted = true;
36 break;
37 }
38 }
39
40 if !is_quoted {
41 value.push_str(base_value);
42 }
43
44 Self {
45 quoted_value,
46 value,
47 }
48 }
49
50 pub fn new_quoted(
51 value_without_quotes: impl AsRef<str>,
52 value_with_quotes: impl AsRef<str>,
53 ) -> Self {
54 Self {
55 quoted_value: Some(value_with_quotes.as_ref().into()),
56 value: value_without_quotes.as_ref().into(),
57 }
58 }
59
60 pub fn new_unquoted(value: impl AsRef<str>) -> Self {
61 Self {
62 quoted_value: None,
63 value: value.as_ref().into(),
64 }
65 }
66
67 pub fn is_empty(&self) -> bool {
68 self.value.is_empty()
69 }
70
71 pub fn is_quoted(&self) -> bool {
72 self.quoted_value.is_some()
73 }
74
75 pub fn get_value(&self) -> &str {
76 self.quoted_value.as_deref().unwrap_or(&self.value)
77 }
78}
79
80impl From<TaskArg> for String {
81 fn from(arg: TaskArg) -> Self {
82 arg.get_value().into()
84 }
85}
86
87impl From<String> for TaskArg {
88 fn from(value: String) -> Self {
89 Self::new(value)
91 }
92}
93
94impl From<&str> for TaskArg {
95 fn from(value: &str) -> Self {
96 Self::new(value)
98 }
99}
100
101impl PartialEq<&str> for TaskArg {
102 fn eq(&self, other: &&str) -> bool {
103 &self.value == other
104 }
105}
106
107impl AsRef<str> for TaskArg {
108 fn as_ref(&self) -> &str {
109 &self.value
110 }
111}
112
113impl Deref for TaskArg {
114 type Target = String;
115
116 fn deref(&self) -> &Self::Target {
117 &self.value
118 }
119}