metadata_gen/tokio.rs
1// SPDX-FileCopyrightText: 2024 - 2026 metadata-gen contributors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Async file helpers on the Tokio runtime (feature `tokio`).
5//!
6//! Other runtimes do not need an adapter: read the file with your own
7//! runtime and hand the text to [`crate::extract_and_prepare_metadata`],
8//! or wrap [`crate::io::extract_from_file`] in a blocking task.
9
10use crate::error::MetadataError;
11use crate::io::extract_from_content;
12use crate::{Keywords, MetaTagGroups, MetadataMap};
13use ::tokio::io::{AsyncRead, AsyncReadExt};
14use std::path::Path;
15
16/// Reads everything from `reader` and runs [`crate::extract_and_prepare_metadata`].
17///
18/// # Errors
19///
20/// [`MetadataError::IoError`] when the read fails, otherwise whatever
21/// [`crate::extract_and_prepare_metadata`] returns.
22///
23/// # Example
24///
25/// ```
26/// # tokio::runtime::Runtime::new().unwrap().block_on(async {
27/// use metadata_gen::tokio::extract_from_reader;
28///
29/// let doc = b"---\ntitle: Async\n---\n" as &[u8];
30/// let (metadata, _, _) = extract_from_reader(doc).await.unwrap();
31/// assert_eq!(metadata["title"], "Async");
32/// # });
33/// ```
34pub async fn extract_from_reader<R: AsyncRead + Unpin>(
35 mut reader: R,
36) -> Result<(MetadataMap, Keywords, MetaTagGroups), MetadataError> {
37 let mut content = String::new();
38 reader.read_to_string(&mut content).await?;
39 extract_from_content(&content)
40}
41
42/// Reads the file at `path` asynchronously and runs
43/// [`crate::extract_and_prepare_metadata`].
44///
45/// # Errors
46///
47/// As [`extract_from_reader`].
48///
49/// # Security
50///
51/// `path` is opened as given. Validate a path that comes from untrusted
52/// input before passing it, to rule out path traversal.
53///
54/// # Example
55///
56/// ```no_run
57/// # tokio::runtime::Runtime::new().unwrap().block_on(async {
58/// use metadata_gen::tokio::extract_from_file;
59///
60/// let (metadata, keywords, tags) = extract_from_file("content/post.md").await.unwrap();
61/// # let _ = (metadata, keywords, tags);
62/// # });
63/// ```
64pub async fn extract_from_file<P: AsRef<Path>>(
65 path: P,
66) -> Result<(MetadataMap, Keywords, MetaTagGroups), MetadataError> {
67 let file = ::tokio::fs::File::open(path).await?;
68 extract_from_reader(file).await
69}