1#![deny(
2 missing_debug_implementations,
3 missing_docs,
4 missing_copy_implementations
5)]
6#![forbid(unsafe_code)]
7
8pub mod gemtext;
17pub mod header;
18pub mod request;
19pub mod response;
20pub mod status;
21
22pub use gemtext::{Builder, Doc, Level};
23pub use header::{Header, MetaKind};
24pub use request::{AnyRequest, GeminiRequest, InvalidRequest, Request, Url};
25pub use response::Response;
26pub use status::{Category, Code, InvalidStatusCode, Status};
27
28#[cfg(feature = "parsers")]
32pub mod parse {
33 use nom::{error::Error, Finish};
34 use paste::paste;
35
36 pub use nom::Err;
37
38 use crate::{gemtext, header, request, response, status};
39
40 macro_rules! parsers {
41 ($(
42 $(#[$doc:meta])*
43 $name:ident: $type:ident
44 ),*) => {
45 $(
46 paste! {
47 $(#[$doc])*
48 pub fn [< parse_ $name >](input: impl AsRef<[u8]>) -> Result<$name::$type, Error<String>> {
49 let bytes = input.as_ref();
50 match $name::parse::$name(bytes).finish() {
51 Ok((_, res)) => Ok(res),
52 Err(Error { input, code }) => Err({
53 let bytes = input.to_owned();
54 let input = String::from_utf8_lossy(&bytes).to_string();
55 Error { input, code }
56 })
57 }
58 }
59 }
60 )*
61 };
62 }
63
64 parsers!(
65 header: Header,
67 request: AnyRequest,
69 response: Response,
71 status: Status
73 );
74
75 pub fn parse_gemtext(input: impl AsRef<str>) -> Result<gemtext::Builder, Error<String>> {
77 let input = input.as_ref();
78 match gemtext::parse::document(input).finish() {
79 Ok((_, res)) => Ok(res),
80 Err(Error { input, code }) => Err({
81 let input = input.to_string();
82 Error { input, code }
83 }),
84 }
85 }
86}