Author: Manos Pitsidianakis [manos@pitsidianak.is]
Hash: 5698cb2bcba9b68e512591106c81d4d93fc596b7
Timestamp: Fri, 05 May 2023 13:58:48 +0000 (1 year ago)

+209 -19 +/-4 browse
core: add doc examples
1diff --git a/Makefile b/Makefile
2index 54adb8b..30457cd 100644
3--- a/Makefile
4+++ b/Makefile
5 @@ -25,3 +25,7 @@ test: check lint
6 .PHONY: rustdoc
7 rustdoc:
8 @RUSTDOCFLAGS="--html-before-content ./.github/doc_extra.html" cargo doc --workspace --all-features --no-deps --document-private-items
9+
10+ .PHONY: rustdoc-open
11+ rustdoc-open:
12+ @RUSTDOCFLAGS="--html-before-content ./.github/doc_extra.html" cargo doc --workspace --all-features --no-deps --document-private-items --open
13 diff --git a/core/src/connection.rs b/core/src/connection.rs
14index 235e878..7d3e619 100644
15--- a/core/src/connection.rs
16+++ b/core/src/connection.rs
17 @@ -138,6 +138,41 @@ impl Connection {
18 /// `Connection` supports a limited subset of operations by default (see
19 /// [`Connection::untrusted`]).
20 /// Use [`Connection::trusted`] to remove these limits.
21+ ///
22+ /// # Example
23+ ///
24+ /// ```rust
25+ /// use mailpot::{Connection, Configuration};
26+ /// use melib::smtp::{SmtpServerConf, SmtpAuth, SmtpSecurity};
27+ /// #
28+ /// # fn main() -> mailpot::Result<()> {
29+ /// # use tempfile::TempDir;
30+ /// #
31+ /// # let tmp_dir = TempDir::new()?;
32+ /// # let db_path = tmp_dir.path().join("mpot.db");
33+ /// # let data_path = tmp_dir.path().to_path_buf();
34+ /// let config = Configuration {
35+ /// send_mail: mailpot::SendMail::Smtp(
36+ /// SmtpServerConf {
37+ /// hostname: "127.0.0.1".into(),
38+ /// port: 25,
39+ /// envelope_from: "foo-chat@example.com".into(),
40+ /// auth: SmtpAuth::None,
41+ /// security: SmtpSecurity::None,
42+ /// extensions: Default::default(),
43+ /// }
44+ /// ),
45+ /// db_path,
46+ /// data_path,
47+ /// administrators: vec![],
48+ /// };
49+ /// # assert_eq!(&Connection::open_db(config.clone()).unwrap_err().to_string(), "Database doesn't exist");
50+ ///
51+ /// let db = Connection::open_or_create_db(config)?;
52+ /// # _ = db;
53+ /// # Ok(())
54+ /// # }
55+ /// ```
56 pub fn open_db(conf: Configuration) -> Result<Self> {
57 use std::sync::Once;
58
59 diff --git a/core/src/doctests/db_setup.rs.inc b/core/src/doctests/db_setup.rs.inc
60new file mode 100644
61index 0000000..bb38811
62--- /dev/null
63+++ b/core/src/doctests/db_setup.rs.inc
64 @@ -0,0 +1,52 @@
65+ # use mailpot::{*, models::*};
66+ # use melib::smtp::{SmtpServerConf, SmtpAuth, SmtpSecurity};
67+ #
68+ # use tempfile::TempDir;
69+ #
70+ # let tmp_dir = TempDir::new()?;
71+ # let db_path = tmp_dir.path().join("mpot.db");
72+ # let data_path = tmp_dir.path().to_path_buf();
73+ # let config = Configuration {
74+ # send_mail: mailpot::SendMail::Smtp(
75+ # SmtpServerConf {
76+ # hostname: "127.0.0.1".into(),
77+ # port: 25,
78+ # envelope_from: "foo-chat@example.com".into(),
79+ # auth: SmtpAuth::None,
80+ # security: SmtpSecurity::None,
81+ # extensions: Default::default(),
82+ # }
83+ # ),
84+ # db_path,
85+ # data_path,
86+ # administrators: vec![],
87+ # };
88+ # let db = Connection::open_or_create_db(config)?.trusted();
89+ # let list = db
90+ # .create_list(MailingList {
91+ # pk: 5,
92+ # name: "foobar chat".into(),
93+ # id: "foo-chat".into(),
94+ # address: "foo-chat@example.com".into(),
95+ # description: Some("Hello world, from foo-chat list".into()),
96+ # archive_url: Some("https://lists.example.com".into()),
97+ # })
98+ # .unwrap();
99+ # let sub_policy = SubscriptionPolicy {
100+ # pk: 1,
101+ # list: 5,
102+ # send_confirmation: true,
103+ # open: false,
104+ # manual: false,
105+ # request: true,
106+ # custom: false,
107+ # };
108+ # let post_policy = PostPolicy {
109+ # pk: 1,
110+ # list: 5,
111+ # announce_only: false,
112+ # subscription_only: false,
113+ # approval_needed: false,
114+ # open: true,
115+ # custom: false,
116+ # };
117 diff --git a/core/src/models.rs b/core/src/models.rs
118index d743829..fbac235 100644
119--- a/core/src/models.rs
120+++ b/core/src/models.rs
121 @@ -28,6 +28,18 @@ use std::borrow::Cow;
122 use melib::email::Address;
123
124 /// A database entry and its primary key. Derefs to its inner type.
125+ ///
126+ /// # Example
127+ ///
128+ /// ```rust,no_run
129+ /// # use mailpot::{*, models::*};
130+ /// # fn foo(db: &Connection) {
131+ /// let val: Option<DbVal<MailingList>> = db.list(5).unwrap();
132+ /// if let Some(list) = val {
133+ /// assert_eq!(list.pk(), 5);
134+ /// }
135+ /// # }
136+ /// ```
137 #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
138 #[serde(transparent)]
139 pub struct DbVal<T>(pub T, #[serde(skip)] pub i64);
140 @@ -105,13 +117,34 @@ impl std::fmt::Display for MailingList {
141 }
142
143 impl MailingList {
144- /// Mailing list display name (e.g. `list name <list_address@example.com>`).
145+ /// Mailing list display name.
146+ ///
147+ /// # Example
148+ ///
149+ /// ```rust
150+ /// # fn main() -> mailpot::Result<()> {
151+ #[doc = include_str!("./doctests/db_setup.rs.inc")]
152+ /// assert_eq!(
153+ /// &list.display_name(),
154+ /// "\"foobar chat\" <foo-chat@example.com>"
155+ /// );
156+ /// # Ok(())
157+ /// # }
158 pub fn display_name(&self) -> String {
159 format!("\"{}\" <{}>", self.name, self.address)
160 }
161
162 #[inline]
163 /// Request subaddress.
164+ ///
165+ /// # Example
166+ ///
167+ /// ```rust
168+ /// # fn main() -> mailpot::Result<()> {
169+ #[doc = include_str!("./doctests/db_setup.rs.inc")]
170+ /// assert_eq!(&list.request_subaddr(), "foo-chat+request@example.com");
171+ /// # Ok(())
172+ /// # }
173 pub fn request_subaddr(&self) -> String {
174 let p = self.address.split('@').collect::<Vec<&str>>();
175 format!("{}+request@{}", p[0], p[1])
176 @@ -120,6 +153,17 @@ impl MailingList {
177 /// Value of `List-Id` header.
178 ///
179 /// See RFC2919 Section 3: <https://www.rfc-editor.org/rfc/rfc2919>
180+ ///
181+ /// # Example
182+ ///
183+ /// ```rust
184+ /// # fn main() -> mailpot::Result<()> {
185+ #[doc = include_str!("./doctests/db_setup.rs.inc")]
186+ /// assert_eq!(
187+ /// &list.id_header(),
188+ /// "Hello world, from foo-chat list <foo-chat.example.com>");
189+ /// # Ok(())
190+ /// # }
191 pub fn id_header(&self) -> String {
192 let p = self.address.split('@').collect::<Vec<&str>>();
193 format!(
194 @@ -134,6 +178,18 @@ impl MailingList {
195 /// Value of `List-Help` header.
196 ///
197 /// See RFC2369 Section 3.1: <https://www.rfc-editor.org/rfc/rfc2369#section-3.1>
198+ ///
199+ /// # Example
200+ ///
201+ /// ```rust
202+ /// # fn main() -> mailpot::Result<()> {
203+ #[doc = include_str!("./doctests/db_setup.rs.inc")]
204+ /// assert_eq!(
205+ /// &list.help_header().unwrap(),
206+ /// "<mailto:foo-chat+request@example.com?subject=help>"
207+ /// );
208+ /// # Ok(())
209+ /// # }
210 pub fn help_header(&self) -> Option<String> {
211 Some(format!("<mailto:{}?subject=help>", self.request_subaddr()))
212 }
213 @@ -141,6 +197,19 @@ impl MailingList {
214 /// Value of `List-Post` header.
215 ///
216 /// See RFC2369 Section 3.4: <https://www.rfc-editor.org/rfc/rfc2369#section-3.4>
217+ ///
218+ /// # Example
219+ ///
220+ /// ```rust
221+ /// # fn main() -> mailpot::Result<()> {
222+ #[doc = include_str!("./doctests/db_setup.rs.inc")]
223+ /// assert_eq!(&list.post_header(None).unwrap(), "NO");
224+ /// assert_eq!(
225+ /// &list.post_header(Some(&post_policy)).unwrap(),
226+ /// "<mailto:foo-chat@example.com>"
227+ /// );
228+ /// # Ok(())
229+ /// # }
230 pub fn post_header(&self, policy: Option<&PostPolicy>) -> Option<String> {
231 Some(policy.map_or_else(
232 || "NO".to_string(),
233 @@ -157,18 +226,26 @@ impl MailingList {
234 /// Value of `List-Unsubscribe` header.
235 ///
236 /// See RFC2369 Section 3.2: <https://www.rfc-editor.org/rfc/rfc2369#section-3.2>
237+ ///
238+ /// # Example
239+ ///
240+ /// ```rust
241+ /// # fn main() -> mailpot::Result<()> {
242+ #[doc = include_str!("./doctests/db_setup.rs.inc")]
243+ /// assert_eq!(
244+ /// &list.unsubscribe_header(Some(&sub_policy)).unwrap(),
245+ /// "<mailto:foo-chat+request@example.com?subject=unsubscribe>"
246+ /// );
247+ /// # Ok(())
248+ /// # }
249 pub fn unsubscribe_header(&self, policy: Option<&SubscriptionPolicy>) -> Option<String> {
250 policy.map_or_else(
251 || None,
252- |p| {
253- if p.open {
254- None
255- } else {
256- Some(format!(
257- "<mailto:{}?subject=unsubscribe>",
258- self.request_subaddr()
259- ))
260- }
261+ |_| {
262+ Some(format!(
263+ "<mailto:{}?subject=unsubscribe>",
264+ self.request_subaddr()
265+ ))
266 },
267 )
268 }
269 @@ -176,18 +253,27 @@ impl MailingList {
270 /// Value of `List-Subscribe` header.
271 ///
272 /// See RFC2369 Section 3.3: <https://www.rfc-editor.org/rfc/rfc2369#section-3.3>
273+ ///
274+ /// # Example
275+ ///
276+ /// ```rust
277+ /// # fn main() -> mailpot::Result<()> {
278+ #[doc = include_str!("./doctests/db_setup.rs.inc")]
279+ /// assert_eq!(
280+ /// &list.subscribe_header(Some(&sub_policy)).unwrap(),
281+ /// "<mailto:foo-chat+request@example.com?subject=subscribe>",
282+ /// );
283+ /// # Ok(())
284+ /// # }
285+ /// ```
286 pub fn subscribe_header(&self, policy: Option<&SubscriptionPolicy>) -> Option<String> {
287 policy.map_or_else(
288 || None,
289- |p| {
290- if p.open {
291- None
292- } else {
293- Some(format!(
294- "<mailto:{}?subject=subscribe>",
295- self.request_subaddr()
296- ))
297- }
298+ |_| {
299+ Some(format!(
300+ "<mailto:{}?subject=subscribe>",
301+ self.request_subaddr()
302+ ))
303 },
304 )
305 }
306 @@ -195,6 +281,19 @@ impl MailingList {
307 /// Value of `List-Archive` header.
308 ///
309 /// See RFC2369 Section 3.6: <https://www.rfc-editor.org/rfc/rfc2369#section-3.6>
310+ ///
311+ /// # Example
312+ ///
313+ /// ```rust
314+ /// # fn main() -> mailpot::Result<()> {
315+ #[doc = include_str!("./doctests/db_setup.rs.inc")]
316+ /// assert_eq!(
317+ /// &list.archive_header().unwrap(),
318+ /// "<https://lists.example.com>"
319+ /// );
320+ /// # Ok(())
321+ /// # }
322+ /// ```
323 pub fn archive_header(&self) -> Option<String> {
324 self.archive_url.as_ref().map(|url| format!("<{}>", url))
325 }