lib.rs
#![deny(
missing_debug_implementations,
missing_docs,
missing_copy_implementations
)]
#![forbid(unsafe_code)]
//! A general purpose library of types for working with the Gemini protocol
//!
//! Represented are Gemini requests, responses, headers, and status codes.
//! Requests are currently just a small layer of functionality over top of a
//! `Url` from the aptly named `url` crate. All types are implemented with an
//! eye towards implementing the Gemini specification faithfully and making
//! illegal or invalid states unrepresentable.
pub mod gemtext;
pub mod header;
pub mod request;
pub mod response;
pub mod status;
pub use gemtext::{Builder, Doc, Level};
pub use header::{Header, MetaKind};
pub use request::{AnyRequest, GeminiRequest, InvalidRequest, Request, Url};
pub use response::Response;
pub use status::{Category, Code, InvalidStatusCode, Status};
/// Helper module with parsers for *COMPLETE* streams of bytes. If you want
/// streaming/resumable parsers, use the parser functions in each submodule
/// directly. Gemtext parsers only work with complete input.
#[cfg(feature = "parsers")]
pub mod parse {
use nom::{error::Error, Finish};
use paste::paste;
pub use nom::Err;
use crate::{gemtext, header, request, response, status};
macro_rules! parsers {
($(
$(#[$doc:meta])*
$name:ident: $type:ident
),*) => {
$(
paste! {
$(#[$doc])*
pub fn [< parse_ $name >](input: impl AsRef<[u8]>) -> Result<$name::$type, Error<String>> {
let bytes = input.as_ref();
match $name::parse::$name(bytes).finish() {
Ok((_, res)) => Ok(res),
Err(Error { input, code }) => Err({
let bytes = input.to_owned();
let input = String::from_utf8_lossy(&bytes).to_string();
Error { input, code }
})
}
}
}
)*
};
}
parsers!(
/// Parse a complete `Header` from bytes.
header: Header,
/// Parse a complete `Request` from bytes.
request: AnyRequest,
/// Parse a complete `Response` from bytes.
response: Response,
/// Parse a complete `Status` from bytes.
status: Status
);
/// Parse a gemtext document from utf-8 text.
pub fn parse_gemtext(input: impl AsRef<str>) -> Result<gemtext::Builder, Error<String>> {
let input = input.as_ref();
match gemtext::parse::document(input).finish() {
Ok((_, res)) => Ok(res),
Err(Error { input, code }) => Err({
let input = input.to_string();
Error { input, code }
}),
}
}
}