Skip to content

Commit

Permalink
Begin work on OCI example.
Browse files Browse the repository at this point in the history
  • Loading branch information
CathalMullan committed Aug 30, 2024
1 parent e9a8342 commit 69db8cd
Show file tree
Hide file tree
Showing 19 changed files with 187 additions and 172 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ corpus
artifacts
coverage

# OCI
junit.xml
report.html

# Nix
result
result-dev
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

...
### Changed

- Fleshed out hyper example.

### Fixed

- Router display no longer relies on generic being displayable.

## [0.2.0] - 2024-08-29

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,22 @@ license = "MIT OR Apache-2.0"
keywords = ["router"]
categories = ["network-programming", "web-programming"]

# https://doc.rust-lang.org/rustc/lints/groups.html
[workspace.lints.rust]
unsafe_code = "forbid"

future-incompatible = { level = "deny", priority = -1 }
keyword-idents = { level = "deny", priority = -1 }
let-underscore = { level = "deny", priority = -1 }
nonstandard-style = { level = "deny", priority = -1 }
refining-impl-trait = { level = "deny", priority = -1 }
rust-2018-compatibility = { level = "deny", priority = -1 }
rust-2018-idioms = { level = "deny", priority = -1 }
rust-2021-compatibility = { level = "deny", priority = -1 }
rust-2024-compatibility = { level = "deny", priority = -1 }
unused = { level = "deny", priority = -2 }

# https://rust-lang.github.io/rust-clippy/master/index.html
[workspace.lints.clippy]
cargo = { level = "deny", priority = -1 }
complexity = { level = "deny", priority = -1 }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ fn main() -> Result<(), Box<dyn Error>> {
router.insert("/user/logout", 12)?;
router.insert("/user/{username}", 13)?;

assert_eq!(router.to_string(), ROUTER_DISPLAY.trim_start());
assert_eq!(router.to_string(), ROUTER_DISPLAY.trim());
Ok(())
}
```
Expand Down
16 changes: 8 additions & 8 deletions benches/matchit_divan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fn main() {
}

#[divan::bench(name = "wayfind")]
fn wayfind(bencher: divan::Bencher) {
fn wayfind(bencher: divan::Bencher<'_, '_>) {
let mut router = wayfind::Router::new();
for route in routes!(brackets) {
router.insert(route, true).unwrap();
Expand All @@ -35,7 +35,7 @@ fn wayfind(bencher: divan::Bencher) {
}

#[divan::bench(name = "actix-router")]
fn actix_router(bencher: divan::Bencher) {
fn actix_router(bencher: divan::Bencher<'_, '_>) {
let mut router = actix_router::Router::<bool>::build();
for route in routes!(brackets) {
router.path(route, true);
Expand All @@ -54,7 +54,7 @@ fn actix_router(bencher: divan::Bencher) {
}

#[divan::bench(name = "matchit")]
fn matchit(bencher: divan::Bencher) {
fn matchit(bencher: divan::Bencher<'_, '_>) {
let mut router = matchit::Router::new();
for route in routes!(brackets) {
router.insert(route, true).unwrap();
Expand All @@ -71,7 +71,7 @@ fn matchit(bencher: divan::Bencher) {
}

#[divan::bench(name = "ntex-router")]
fn ntex_router(bencher: divan::Bencher) {
fn ntex_router(bencher: divan::Bencher<'_, '_>) {
let mut router = ntex_router::Router::<bool>::build();
for route in routes!(brackets) {
router.path(route, true);
Expand All @@ -90,7 +90,7 @@ fn ntex_router(bencher: divan::Bencher) {
}

#[divan::bench(name = "path-tree")]
fn path_tree(bencher: divan::Bencher) {
fn path_tree(bencher: divan::Bencher<'_, '_>) {
let mut router = path_tree::PathTree::new();
for route in routes!(colon) {
let _ = router.insert(route, true);
Expand All @@ -107,7 +107,7 @@ fn path_tree(bencher: divan::Bencher) {
}

#[divan::bench(name = "route-recognizer")]
fn route_recognizer(bencher: divan::Bencher) {
fn route_recognizer(bencher: divan::Bencher<'_, '_>) {
let mut router = route_recognizer::Router::new();
for route in routes!(colon) {
router.add(route, true);
Expand All @@ -124,7 +124,7 @@ fn route_recognizer(bencher: divan::Bencher) {
}

#[divan::bench(name = "routefinder")]
fn routefinder(bencher: divan::Bencher) {
fn routefinder(bencher: divan::Bencher<'_, '_>) {
let mut router = routefinder::Router::new();
for route in routes!(colon) {
router.add(route, true).unwrap();
Expand All @@ -141,7 +141,7 @@ fn routefinder(bencher: divan::Bencher) {
}

#[divan::bench(name = "xitca-router")]
fn xitca_router(bencher: divan::Bencher) {
fn xitca_router(bencher: divan::Bencher<'_, '_>) {
let mut router = xitca_router::Router::new();
for route in routes!(colon) {
router.insert(route, true).unwrap();
Expand Down
16 changes: 8 additions & 8 deletions benches/path_tree_divan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fn main() {
}

#[divan::bench(name = "wayfind")]
fn wayfind(bencher: divan::Bencher) {
fn wayfind(bencher: divan::Bencher<'_, '_>) {
let mut router = wayfind::Router::new();
for (index, route) in routes!(brackets).iter().enumerate() {
router.insert(route, index).unwrap();
Expand All @@ -35,7 +35,7 @@ fn wayfind(bencher: divan::Bencher) {
}

#[divan::bench(name = "actix-router")]
fn actix_router(bencher: divan::Bencher) {
fn actix_router(bencher: divan::Bencher<'_, '_>) {
let mut router = actix_router::Router::<usize>::build();
for (index, route) in routes!(brackets).iter().enumerate() {
router.path(*route, index);
Expand All @@ -54,7 +54,7 @@ fn actix_router(bencher: divan::Bencher) {
}

#[divan::bench(name = "matchit")]
fn matchit(bencher: divan::Bencher) {
fn matchit(bencher: divan::Bencher<'_, '_>) {
let mut router = matchit::Router::new();
for (index, route) in routes!(brackets).iter().enumerate() {
router.insert(*route, index).unwrap();
Expand All @@ -71,7 +71,7 @@ fn matchit(bencher: divan::Bencher) {
}

#[divan::bench(name = "ntex-router")]
fn ntex_router(bencher: divan::Bencher) {
fn ntex_router(bencher: divan::Bencher<'_, '_>) {
let mut router = ntex_router::Router::<usize>::build();
for (index, route) in routes!(brackets).iter().enumerate() {
router.path(*route, index);
Expand All @@ -90,7 +90,7 @@ fn ntex_router(bencher: divan::Bencher) {
}

#[divan::bench(name = "path-tree")]
fn path_tree(bencher: divan::Bencher) {
fn path_tree(bencher: divan::Bencher<'_, '_>) {
let mut router = path_tree::PathTree::new();
for (index, route) in routes!(colon).iter().enumerate() {
let _ = router.insert(route, index);
Expand All @@ -107,7 +107,7 @@ fn path_tree(bencher: divan::Bencher) {
}

#[divan::bench(name = "route-recognizer")]
fn route_recognizer(bencher: divan::Bencher) {
fn route_recognizer(bencher: divan::Bencher<'_, '_>) {
let mut router = route_recognizer::Router::<usize>::new();
for (index, route) in routes!(colon).iter().enumerate() {
router.add(route, index);
Expand All @@ -124,7 +124,7 @@ fn route_recognizer(bencher: divan::Bencher) {
}

#[divan::bench(name = "routefinder")]
fn routefinder(bencher: divan::Bencher) {
fn routefinder(bencher: divan::Bencher<'_, '_>) {
let mut router = routefinder::Router::new();
for (index, route) in routes!(colon).iter().enumerate() {
router.add(*route, index).unwrap();
Expand All @@ -141,7 +141,7 @@ fn routefinder(bencher: divan::Bencher) {
}

#[divan::bench(name = "xitca-router")]
fn xitca_router(bencher: divan::Bencher) {
fn xitca_router(bencher: divan::Bencher<'_, '_>) {
let mut router = xitca_router::Router::new();
for (index, route) in routes!(colon).iter().enumerate() {
router.insert(*route, index).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion examples/hyper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ publish = false
version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
repository.workspace = true
license.workspace = true
keywords.workspace = true
Expand All @@ -28,3 +27,4 @@ bytes = "1.7"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"
regex = "1.10"
7 changes: 7 additions & 0 deletions examples/hyper/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# `hyper` example

This is a mini implementation of an [Open Container Initiative (OCI) Distribution Specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md) registry.

## Inspirations:
- https://github.com/mcronce/oci-registry
- https://github.com/Trow-Registry/trow
92 changes: 8 additions & 84 deletions examples/hyper/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,28 @@
#![allow(clippy::unused_async)]

use bytes::Bytes;
use http_body_util::{combinators::BoxBody, BodyExt, Full};
use hyper::{body::Incoming, header, service::service_fn, Request, Response, StatusCode};
use hyper::{body::Incoming, service::service_fn, Request};
use hyper_util::{
rt::{TokioExecutor, TokioIo},
server::conn::auto::Builder,
};
use routes::router;
use std::{
convert::Infallible,
future::Future,
net::{IpAddr, Ipv4Addr, SocketAddr},
pin::Pin,
sync::Arc,
};
use tokio::{net::TcpListener, task::JoinSet};
use wayfind::{Parameter, Path, Router};

type BoxFuture<'a> = Pin<
Box<
dyn Future<Output = Result<Response<BoxBody<Bytes, Infallible>>, anyhow::Error>>
+ Send
+ 'a,
>,
>;
use wayfind::Path;

type HandlerFn =
Arc<dyn for<'a> Fn(&'a str, &'a [Parameter<'_, 'a>]) -> BoxFuture<'a> + Send + Sync>;
pub mod routes;

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let mut router: Router<HandlerFn> = Router::new();
router.insert(
"/",
Arc::new(move |path, parameters| Box::pin(index_route(path, parameters))),
)?;
router.insert(
"/hello/{name}",
Arc::new(move |path, parameters| Box::pin(hello_route(path, parameters))),
)?;
router.insert(
"{*catch_all}",
Arc::new(move |path, parameters| Box::pin(not_found(path, parameters))),
)?;

let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1337);
let listener = TcpListener::bind(&socket).await?;
println!("Listening on http://{socket}");

let router = router()?;
let router = Arc::new(router);
println!("Router: {router}");

let mut join_set = JoinSet::new();

loop {
Expand All @@ -58,7 +32,7 @@ async fn main() -> Result<(), anyhow::Error> {

let router = Arc::clone(&router);
join_set.spawn(async move {
let _ = Builder::new(TokioExecutor::new())
let _unused = Builder::new(TokioExecutor::new())
.serve_connection(
TokioIo::new(stream),
service_fn(move |request: Request<Incoming>| {
Expand All @@ -81,53 +55,3 @@ async fn main() -> Result<(), anyhow::Error> {
});
}
}

async fn index_route(
_: &'_ str,
_: &'_ [Parameter<'_, '_>],
) -> Result<Response<BoxBody<Bytes, Infallible>>, anyhow::Error> {
let json = serde_json::json!({
"hello": "world"
});

let body = Full::new(Bytes::from(json.to_string()));
let response = Response::builder()
.header(header::CONTENT_TYPE, "application/json")
.body(body.boxed())?;

Ok(response)
}

async fn hello_route(
_: &'_ str,
parameters: &'_ [Parameter<'_, '_>],
) -> Result<Response<BoxBody<Bytes, Infallible>>, anyhow::Error> {
let name = parameters[0].value;
let json = serde_json::json!({
"hello": name,
});

let body = Full::new(Bytes::from(json.to_string()));
let response = Response::builder()
.header(header::CONTENT_TYPE, "application/json")
.body(body.boxed())?;

Ok(response)
}

async fn not_found(
path: &'_ str,
_: &'_ [Parameter<'_, '_>],
) -> Result<Response<BoxBody<Bytes, Infallible>>, anyhow::Error> {
let json = serde_json::json!({
"error": "route_not_found",
"route": path,
});

let body = Full::new(Bytes::from(json.to_string()));
let response = Response::builder()
.status(StatusCode::NOT_FOUND)
.body(body.boxed())?;

Ok(response)
}
32 changes: 32 additions & 0 deletions examples/hyper/src/routes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#![allow(clippy::unused_async)]

use bytes::Bytes;
use http_body_util::combinators::BoxBody;
use hyper::Response;
use index::index_route;
use std::{convert::Infallible, future::Future, pin::Pin, sync::Arc};
use wayfind::{errors::InsertError, Parameter, Router};

pub mod index;

type BoxFuture<'a> = Pin<
Box<
dyn Future<Output = Result<Response<BoxBody<Bytes, Infallible>>, anyhow::Error>>
+ Send
+ 'a,
>,
>;

type HandlerFn =
Arc<dyn for<'a> Fn(&'a str, &'a [Parameter<'_, 'a>]) -> BoxFuture<'a> + Send + Sync>;

pub fn router() -> Result<Router<HandlerFn>, InsertError> {
let mut router: Router<HandlerFn> = Router::new();

router.insert(
"/",
Arc::new(move |path, parameters| Box::pin(index_route(path, parameters))),
)?;

Ok(router)
}
Loading

0 comments on commit 69db8cd

Please sign in to comment.