1use crate::*;
2
3impl<'a> CookieBuilder<'a> {
5 pub fn parse(cookie: &'a str) -> Self {
18 let parts: Vec<&str> = cookie.split(SEMICOLON).collect();
19 if parts.is_empty() {
20 return Self::default();
21 }
22 let mut name: &str = "";
23 let mut value: &str = "";
24 if let Some(name_value_pair) = parts.first() {
25 let name_value_pair: &str = name_value_pair.trim();
26 if let Some((n, v)) = name_value_pair.split_once(EQUAL) {
27 name = n.trim();
28 value = v.trim();
29 } else if !name_value_pair.is_empty() {
30 name = name_value_pair;
31 value = "";
32 }
33 }
34 let mut expires: &str = "";
35 let mut max_age: i64 = 0i64;
36 let mut domain: &str = "";
37 let mut path: &str = "";
38 let mut secure: bool = false;
39 let mut http_only: bool = false;
40 let mut same_site: &str = "";
41 for part in parts.iter().skip(1) {
42 let part: &str = part.trim();
43 if part.is_empty() {
44 continue;
45 }
46 if let Some((key, val)) = part.split_once(EQUAL) {
47 let key_lowercase: String = key.trim().to_lowercase();
48 let val: &str = val.trim();
49 match key_lowercase.as_str() {
50 COOKIE_EXPIRES_LOWERCASE => {
51 expires = val;
52 }
53 COOKIE_MAX_AGE_LOWERCASE => {
54 if let Ok(max_age_value) = val.parse::<i64>() {
55 max_age = max_age_value;
56 }
57 }
58 COOKIE_DOMAIN_LOWERCASE => {
59 domain = val;
60 }
61 COOKIE_PATH_LOWERCASE => {
62 path = val;
63 }
64 COOKIE_SAME_SITE_LOWERCASE => {
65 same_site = val;
66 }
67 _ => {}
68 }
69 } else {
70 let attribute_lowercase: String = part.to_lowercase();
71 match attribute_lowercase.as_str() {
72 COOKIE_SECURE_LOWERCASE => {
73 secure = true;
74 }
75 COOKIE_HTTP_ONLY_LOWERCASE => {
76 http_only = true;
77 }
78 _ => {}
79 }
80 }
81 }
82
83 Self {
84 name,
85 value,
86 expires,
87 max_age,
88 domain,
89 path,
90 secure,
91 http_only,
92 same_site,
93 }
94 }
95
96 pub fn build(&self) -> String {
104 if self.name.is_empty() {
105 return String::new();
106 }
107 let mut cookie_string: String = format!("{}={}", self.name, self.value);
108
109 if !self.expires.is_empty() {
110 cookie_string.push_str(COOKIE_EXPIRES_ATTRIBUTE_LOWERCASE);
111 cookie_string.push_str(self.expires);
112 }
113 if self.max_age > 0 {
114 cookie_string.push_str(COOKIE_MAX_AGE_ATTRIBUTE_LOWERCASE);
115 cookie_string.push_str(&self.max_age.to_string());
116 }
117 if !self.domain.is_empty() {
118 cookie_string.push_str(COOKIE_DOMAIN_ATTRIBUTE_LOWERCASE);
119 cookie_string.push_str(self.domain);
120 }
121 if !self.path.is_empty() {
122 cookie_string.push_str(COOKIE_PATH_ATTRIBUTE_LOWERCASE);
123 cookie_string.push_str(self.path);
124 }
125 if self.secure {
126 cookie_string.push_str(COOKIE_SECURE_ATTRIBUTE_LOWERCASE);
127 }
128 if self.http_only {
129 cookie_string.push_str(COOKIE_HTTP_ONLY_ATTRIBUTE_LOWERCASE);
130 }
131 if !self.same_site.is_empty() {
132 cookie_string.push_str(COOKIE_SAME_SITE_ATTRIBUTE_LOWERCASE);
133 cookie_string.push_str(self.same_site);
134 }
135 cookie_string
136 }
137}
138
139impl Cookie {
141 pub fn parse<C>(cookie: C) -> Cookies
154 where
155 C: AsRef<str>,
156 {
157 let cookie_ref: &str = cookie.as_ref();
158 let mut cookies: Cookies = hash_map_xx_hash3_64();
159 if cookie_ref.trim().is_empty() {
160 return cookies;
161 }
162 let parts: Vec<&str> = cookie_ref.split(SEMICOLON).collect();
163 for part in parts {
164 let part: &str = part.trim();
165 if part.is_empty() {
166 continue;
167 }
168 if let Some((name, value)) = part.split_once(EQUAL) {
169 let name: String = name.trim().to_string();
170 let value: String = value.trim().to_string();
171 if !name.is_empty() {
172 cookies.insert(name, value);
173 }
174 } else if !part.is_empty() {
175 cookies.insert(part.to_string(), String::new());
176 }
177 }
178 cookies
179 }
180}