cookie_monster/cookie/
serialize.rs1use crate::{
2 Error, SameSite,
3 cookie::parse::{find_invalid_cookie_value, invalid_token, trim_quotes},
4};
5
6use super::Cookie;
7use std::fmt::Write;
8
9impl Cookie {
10 pub fn serialize(&self) -> crate::Result<String> {
19 self.serialize_inner(|name, value, buf| {
20 let trimmed_value = trim_quotes(value);
23
24 if let Some(invalid_char) = find_invalid_cookie_value(trimmed_value) {
25 return Err(Error::InvalidValue(invalid_char));
26 } else if let Some(token) = invalid_token(name) {
27 return Err(Error::InvalidName(token));
28 }
29
30 let _ = write!(buf, "{name}={value}");
31 Ok(())
32 })
33 }
34
35 #[cfg(feature = "percent-encode")]
43 pub fn serialize_encoded(&self) -> crate::Result<String> {
44 use crate::cookie::encoding::{encode_name, encode_value};
45
46 self.serialize_inner(|name, value, buf| {
47 let _ = write!(buf, "{}={}", encode_name(name), encode_value(value));
49 Ok(())
50 })
51 }
52
53 fn serialize_inner(
54 &self,
55 callback: impl Fn(&str, &str, &mut String) -> crate::Result<()>,
56 ) -> crate::Result<String> {
57 let value = self.value();
58 let name = self.name();
59 let domain = self.domain();
60 let path = self.path();
61
62 if name.is_empty() {
63 return Err(Error::NameEmpty);
64 }
65
66 let buf_len = name.len()
67 + value.len()
68 + domain.map(str::len).unwrap_or_default()
69 + path.map(str::len).unwrap_or_default();
70
71 let mut buf = String::with_capacity(buf_len + 110);
74
75 callback(name, value, &mut buf)?;
78
79 if let Some(max_age) = self.max_age_secs() {
81 buf.push_str("; Max-Age=");
82 write!(&mut buf, "{max_age}").expect("Failed to write Max-Age seconds");
83 }
84
85 self.serialize_domain(&mut buf);
86
87 self.serialize_path(&mut buf)?;
88
89 if self.secure() || self.partitioned() || self.same_site() == Some(SameSite::None) {
91 buf.push_str("; Secure");
92 }
93
94 if self.http_only() {
95 buf.push_str("; HttpOnly");
96 }
97
98 if self.partitioned() {
99 buf.push_str("; Partitioned");
100 }
101
102 self.serialize_same_site(&mut buf);
103
104 self.serialize_expire(&mut buf)?;
105 Ok(buf)
106 }
107}