Macro for creating routes

This commit is contained in:
Martin Berg Alstad 2024-06-17 12:18:53 +02:00
parent 78368772eb
commit 2e9f6cd171
7 changed files with 76 additions and 38 deletions

View File

@ -12,8 +12,9 @@ use nom::sequence::{delimited, terminated};
/// - `inner`: The parser to trim
/// - Returns: A parser that trims leading and trailing whitespace from the input and then runs the value from the inner parser
pub fn trim<'a, Parser, R>(inner: Parser) -> impl FnMut(&'a str) -> IResult<&'a str, R>
where
Parser: Fn(&'a str) -> IResult<&'a str, R> {
where
Parser: Fn(&'a str) -> IResult<&'a str, R>,
{
delimited(
multispace0,
inner,
@ -27,8 +28,9 @@ pub fn trim<'a, Parser, R>(inner: Parser) -> impl FnMut(&'a str) -> IResult<&'a
/// - `inner`: The parser to run inside the parentheses
/// - Returns: A parser that parses a parenthesized expression
pub fn parenthesized<'a, Parser, R>(inner: Parser) -> impl FnMut(&'a str) -> IResult<&'a str, R>
where
Parser: Fn(&'a str) -> IResult<&'a str, R> {
where
Parser: Fn(&'a str) -> IResult<&'a str, R>,
{
delimited(
char('('),
trim(inner),
@ -42,15 +44,19 @@ pub fn parenthesized<'a, Parser, R>(inner: Parser) -> impl FnMut(&'a str) -> IRe
/// - `predicate`: The predicate to call to validate the input
/// - Returns: A parser that takes `n` characters from the input
pub fn take_where<F, Input, Error: ParseError<Input>>(n: usize, predicate: F) -> impl Fn(Input) -> IResult<Input, Input, Error>
where Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>, F: Fn(<Input as InputIter>::Item) -> bool, {
where
Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>,
F: Fn(<Input as InputIter>::Item) -> bool,
{
move |input: Input| {
take_while_m_n(n, n, |it| predicate(it))(input)
}
}
pub fn exhausted<'a, Parser, R>(inner: Parser) -> impl FnMut(&'a str) -> IResult<&'a str, R>
where
Parser: Fn(&'a str) -> IResult<&'a str, R> {
where
Parser: Fn(&'a str) -> IResult<&'a str, R>,
{
terminated(inner, eof)
}

View File

@ -1,16 +1,15 @@
use axum::body::Body;
use axum::http::StatusCode;
use axum::response::{Html, IntoResponse, Response};
use axum::Router;
use axum::routing::get;
use tokio::fs::File;
use tokio_util::io::ReaderStream;
pub fn router() -> Router {
Router::new()
.route("/", get(index))
.route("/openapi", get(open_api))
}
use crate::router;
router!(
get "/" => index,
get "/openapi" => open_api
);
async fn index() -> &'static str {
"Welcome to the Simplify Truths API!\n"

View File

@ -1,22 +1,18 @@
use axum::{Router, routing::get};
use axum::extract::{Path, Query};
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use crate::expressions::expression::Expression;
use crate::expressions::truth_table::TruthTable;
use crate::{router, routes};
use crate::routing::error::{Error, ErrorKind};
use crate::routing::options::{SimplifyAndTableOptions, SimplifyOptions};
use crate::routing::response::SimplifyResponse;
pub fn router() -> Router<()> {
Router::new()
.nest("/simplify",
Router::new()
.route("/:exp", get(simplify))
.route("/table/:exp", get(simplify_and_table)),
)
}
router!("/simplify", routes!(
get "/:exp" => simplify,
get "/table/:exp" => simplify_and_table
));
async fn simplify(Path(path): Path<String>, Query(query): Query<SimplifyOptions>) -> Response {
match Expression::try_from(path.as_str()) {

View File

@ -1,21 +1,17 @@
use axum::extract::{Path, Query};
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::Router;
use axum::routing::get;
use crate::{router, routes};
use crate::expressions::expression::Expression;
use crate::expressions::truth_table::TruthTable;
use crate::routing::error::{Error, ErrorKind};
use crate::routing::options::TruthTableOptions;
use crate::routing::response::TruthTableResponse;
pub fn router() -> Router<()> {
Router::new()
.nest("/table", Router::new()
.route("/:exp", get(table)),
)
}
router!("/table", routes!(
get "/:exp" => table
));
// TODO Expression as input in body
async fn table(Path(value): Path<String>, Query(query): Query<TruthTableOptions>) -> Response {

View File

@ -1,16 +1,14 @@
use axum::extract::Path;
use axum::response::{IntoResponse, Response};
use axum::Router;
use axum::routing::get;
use crate::expressions::expression::Expression;
use crate::router;
use crate::routing::error::{Error, ErrorKind};
use crate::routing::response::IsLegalResponse;
pub fn router() -> Router<()> {
Router::new()
.route("/is-legal/:exp", get(is_legal))
}
router!(
get "/is-legal/:exp" => is_legal
);
async fn is_legal(Path(path): Path<String>) -> Response {
match Expression::try_from(path.as_str()) {

42
src/utils/axum.rs Normal file
View File

@ -0,0 +1,42 @@
/// Create an axum router function with the given body or routes.
/// # Examples
/// ```
/// router!(
/// get "/" => index,
/// get "/openapi" => open_api
/// );
/// router!("/simplify", routes!(
/// get "/:exp" => simplify,
/// get "/table/:exp" => simplify_and_table
/// ));
/// ```
#[macro_export]
macro_rules! router {
($body:expr) => {
pub(crate) fn router() -> axum::Router<()> {
$body
}
};
($route:expr, $router:expr) => {
router!(axum::Router::new().nest($route, $router));
};
($($method:ident $route:expr => $func:expr),* $(,)?) => {
router!($crate::routes!($($method $route => $func),*));
};
}
/// Create a router with the given routes.
/// # Examples
/// ```
/// routes!(
/// get "/" => index,
/// post "/" => create
/// );
/// ```
#[macro_export]
macro_rules! routes {
($($method:ident $route:expr => $func:expr),* $(,)?) => {
axum::Router::new()
$(.route($route, axum::routing::$method($func)))*
};
}

View File

@ -1,2 +1,3 @@
pub mod array;
pub mod serialize;
pub mod serialize;
mod axum;