1use crate::*;
2
3impl CookieBuilder {
5 #[inline(always)]
16 pub fn new<N, V>(name: N, value: V) -> Self
17 where
18 N: AsRef<str>,
19 V: AsRef<str>,
20 {
21 Self {
22 name: name.as_ref().to_owned(),
23 value: value.as_ref().to_owned(),
24 ..Default::default()
25 }
26 }
27
28 pub fn parse<C>(cookie: C) -> Self
41 where
42 C: AsRef<str>,
43 {
44 let mut cookie_builder: Self = Self::default();
45 let parts: Vec<&str> = cookie.as_ref().split(SEMICOLON).collect();
46 if parts.is_empty() {
47 return cookie_builder;
48 }
49 if let Some(name_value_pair) = parts.first() {
50 let name_value_pair: &str = name_value_pair.trim();
51 if let Some((name, value)) = name_value_pair.split_once(EQUAL) {
52 cookie_builder.name = name.trim().to_string();
53 cookie_builder.value = value.trim().to_string();
54 } else if !name_value_pair.is_empty() {
55 cookie_builder.name = name_value_pair.to_string();
56 cookie_builder.value = String::new();
57 }
58 }
59 for part in parts.iter().skip(1) {
60 let part: &str = part.trim();
61 if part.is_empty() {
62 continue;
63 }
64 if let Some((key, value)) = part.split_once(EQUAL) {
65 let key_lowercase: String = key.trim().to_lowercase();
66 let value: String = value.trim().to_string();
67 match key_lowercase.as_str() {
68 COOKIE_EXPIRES_LOWERCASE => {
69 cookie_builder.expires = value;
70 }
71 COOKIE_MAX_AGE_LOWERCASE => {
72 if let Ok(max_age_value) = value.parse::<i64>() {
73 cookie_builder.max_age = max_age_value;
74 }
75 }
76 COOKIE_DOMAIN_LOWERCASE => {
77 cookie_builder.domain = value;
78 }
79 COOKIE_PATH_LOWERCASE => {
80 cookie_builder.path = value;
81 }
82 COOKIE_SAME_SITE_LOWERCASE => {
83 cookie_builder.same_site = value;
84 }
85 _ => {}
86 }
87 } else {
88 let attribute_lowercase: String = part.to_lowercase();
89 match attribute_lowercase.as_str() {
90 COOKIE_SECURE_LOWERCASE => {
91 cookie_builder.secure = true;
92 }
93 COOKIE_HTTP_ONLY_LOWERCASE => {
94 cookie_builder.http_only = true;
95 }
96 _ => {}
97 }
98 }
99 }
100 cookie_builder
101 }
102
103 pub fn build(&self) -> String {
111 if self.name.is_empty() {
112 return String::new();
113 }
114 let mut cookie_string: String = format!("{}={}", self.name, self.value);
115
116 if !self.expires.is_empty() {
117 cookie_string.push_str(COOKIE_EXPIRES_ATTRIBUTE_LOWERCASE);
118 cookie_string.push_str(&self.expires);
119 }
120 if self.max_age > 0 {
121 cookie_string.push_str(COOKIE_MAX_AGE_ATTRIBUTE_LOWERCASE);
122 cookie_string.push_str(&self.max_age.to_string());
123 }
124 if !self.domain.is_empty() {
125 cookie_string.push_str(COOKIE_DOMAIN_ATTRIBUTE_LOWERCASE);
126 cookie_string.push_str(&self.domain);
127 }
128 if !self.path.is_empty() {
129 cookie_string.push_str(COOKIE_PATH_ATTRIBUTE_LOWERCASE);
130 cookie_string.push_str(&self.path);
131 }
132 if self.secure {
133 cookie_string.push_str(COOKIE_SECURE_ATTRIBUTE_LOWERCASE);
134 }
135 if self.http_only {
136 cookie_string.push_str(COOKIE_HTTP_ONLY_ATTRIBUTE_LOWERCASE);
137 }
138 if !self.same_site.is_empty() {
139 cookie_string.push_str(COOKIE_SAME_SITE_ATTRIBUTE_LOWERCASE);
140 cookie_string.push_str(&self.same_site);
141 }
142 cookie_string
143 }
144}
145
146impl Cookie {
148 pub fn parse<C>(cookie: C) -> Cookies
161 where
162 C: AsRef<str>,
163 {
164 let cookie_ref: &str = cookie.as_ref();
165 let mut cookies: Cookies = hash_map_xx_hash3_64();
166 if cookie_ref.trim().is_empty() {
167 return cookies;
168 }
169 let parts: Vec<&str> = cookie_ref.split(SEMICOLON).collect();
170 for part in parts {
171 let part: &str = part.trim();
172 if part.is_empty() {
173 continue;
174 }
175 if let Some((name, value)) = part.split_once(EQUAL) {
176 let name: String = name.trim().to_string();
177 let value: String = value.trim().to_string();
178 if !name.is_empty() {
179 cookies.insert(name, value);
180 }
181 } else if !part.is_empty() {
182 cookies.insert(part.to_string(), String::new());
183 }
184 }
185 cookies
186 }
187}