nntp_proxy/protocol/
commands.rs1use super::RequestContext;
7use crate::types::MessageId;
8
9pub const QUIT: &[u8] = b"QUIT\r\n";
11
12pub const COMPRESS_DEFLATE: &[u8] = b"COMPRESS DEFLATE\r\n";
14
15#[inline]
19#[must_use]
20pub fn authinfo_user(username: &str) -> RequestContext {
21 RequestContext::from_verb_arg_slices(b"AUTHINFO", &[b"USER ", username.as_bytes()])
22}
23
24#[inline]
28#[must_use]
29pub fn authinfo_pass(password: &str) -> RequestContext {
30 RequestContext::from_verb_arg_slices(b"AUTHINFO", &[b"PASS ", password.as_bytes()])
31}
32
33#[inline]
34#[must_use]
35pub fn article_request(msgid: &MessageId<'_>) -> RequestContext {
36 RequestContext::from_verb_args(b"ARTICLE", msgid.as_str().as_bytes())
37}
38
39#[inline]
40#[must_use]
41pub fn body_request(msgid: &MessageId<'_>) -> RequestContext {
42 RequestContext::from_verb_args(b"BODY", msgid.as_str().as_bytes())
43}
44
45#[inline]
46#[must_use]
47pub fn head_request(msgid: &MessageId<'_>) -> RequestContext {
48 RequestContext::from_verb_args(b"HEAD", msgid.as_str().as_bytes())
49}
50
51#[inline]
52#[must_use]
53pub fn stat_request(msgid: &MessageId<'_>) -> RequestContext {
54 RequestContext::from_verb_args(b"STAT", msgid.as_str().as_bytes())
55}
56
57#[inline]
58#[must_use]
59pub fn date_request() -> RequestContext {
60 RequestContext::from_verb_args(b"DATE", b"")
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use futures::executor::block_on;
67
68 fn msgid(value: &str) -> MessageId<'_> {
69 MessageId::from_borrowed(value).unwrap()
70 }
71
72 fn wire(context: &RequestContext) -> Vec<u8> {
73 let mut out = Vec::with_capacity(context.request_wire_len().get());
74 block_on(context.write_wire_to(&mut out)).unwrap();
75 out
76 }
77
78 #[test]
79 fn test_quit_command() {
80 assert_eq!(QUIT, b"QUIT\r\n");
81 }
82
83 #[test]
84 fn test_date_request() {
85 assert_eq!(wire(&date_request()), b"DATE\r\n");
86 }
87
88 #[test]
89 fn test_authinfo_user() {
90 assert_eq!(
91 wire(&authinfo_user("testuser")),
92 b"AUTHINFO USER testuser\r\n"
93 );
94 assert_eq!(wire(&authinfo_user("")), b"AUTHINFO USER \r\n");
95 assert_eq!(
96 authinfo_user("testuser").kind(),
97 crate::protocol::RequestKind::AuthInfo
98 );
99 }
100
101 #[test]
102 fn test_authinfo_user_special_chars() {
103 assert_eq!(
104 wire(&authinfo_user("user@example.com")),
105 b"AUTHINFO USER user@example.com\r\n"
106 );
107 }
108
109 #[test]
110 fn test_authinfo_user_spaces() {
111 assert_eq!(
112 wire(&authinfo_user("user with spaces")),
113 b"AUTHINFO USER user with spaces\r\n"
114 );
115 }
116
117 #[test]
118 fn test_authinfo_pass() {
119 assert_eq!(wire(&authinfo_pass("secret")), b"AUTHINFO PASS secret\r\n");
120 assert_eq!(wire(&authinfo_pass("")), b"AUTHINFO PASS \r\n");
121 assert_eq!(
122 authinfo_pass("secret").kind(),
123 crate::protocol::RequestKind::AuthInfo
124 );
125 }
126
127 #[test]
128 fn test_authinfo_pass_special_chars() {
129 assert_eq!(
130 wire(&authinfo_pass("p@ssw0rd!#$")),
131 b"AUTHINFO PASS p@ssw0rd!#$\r\n"
132 );
133 }
134
135 #[test]
136 fn test_authinfo_pass_spaces() {
137 assert_eq!(
138 wire(&authinfo_pass("pass word")),
139 b"AUTHINFO PASS pass word\r\n"
140 );
141 }
142
143 #[test]
144 fn test_authinfo_crlf_termination() {
145 assert!(wire(&authinfo_user("user")).ends_with(b"\r\n"));
146 assert!(wire(&authinfo_pass("pass")).ends_with(b"\r\n"));
147 }
148
149 #[test]
150 fn test_article_request() {
151 assert_eq!(
152 wire(&article_request(&msgid("<test@example.com>"))),
153 b"ARTICLE <test@example.com>\r\n"
154 );
155 assert_eq!(
156 wire(&article_request(&msgid("<msg123@news.server.com>"))),
157 b"ARTICLE <msg123@news.server.com>\r\n"
158 );
159 }
160
161 #[test]
162 fn test_body_request() {
163 assert_eq!(
164 wire(&body_request(&msgid("<test@example.com>"))),
165 b"BODY <test@example.com>\r\n"
166 );
167 }
168
169 #[test]
170 fn test_head_request() {
171 assert_eq!(
172 wire(&head_request(&msgid("<test@example.com>"))),
173 b"HEAD <test@example.com>\r\n"
174 );
175 }
176
177 #[test]
178 fn test_stat_request() {
179 assert_eq!(
180 wire(&stat_request(&msgid("<test@example.com>"))),
181 b"STAT <test@example.com>\r\n"
182 );
183 }
184
185 #[test]
186 fn test_commands_end_with_crlf() {
187 assert!(wire(&authinfo_user("test")).ends_with(b"\r\n"));
188 assert!(wire(&authinfo_pass("test")).ends_with(b"\r\n"));
189 assert!(wire(&article_request(&msgid("<test@example.com>"))).ends_with(b"\r\n"));
190 assert!(wire(&body_request(&msgid("<test@example.com>"))).ends_with(b"\r\n"));
191 assert!(wire(&head_request(&msgid("<test@example.com>"))).ends_with(b"\r\n"));
192 assert!(wire(&stat_request(&msgid("<test@example.com>"))).ends_with(b"\r\n"));
193 }
194}