Skip to content

Commit c9b37c0

Browse files
authored
Merge pull request #75 from dev-five-git/optimize-1
Optimize 1
2 parents 84d58fa + a4a1459 commit c9b37c0

49 files changed

Lines changed: 2405 additions & 1874 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"changes":{"Cargo.toml":"Patch"},"note":"Hello","date":"2026-02-16T16:40:01.407925800Z"}

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,31 @@
22
resolver = "2"
33
members = ["crates/*", "examples/*"]
44

5+
[workspace.package]
6+
version = "0.1.33"
7+
edition = "2024"
8+
license = "Apache-2.0"
9+
repository = "https://github.com/dev-five-git/vespera"
10+
readme = "README.md"
11+
512
[workspace.dependencies]
613
vespera_core = { path = "crates/vespera_core", version = "0.1.33" }
714
vespera_macro = { path = "crates/vespera_macro", version = "0.1.33" }
15+
16+
[workspace.lints.clippy]
17+
all = { level = "warn", priority = -1 }
18+
pedantic = { level = "warn", priority = -1 }
19+
# cherry-picked nursery lints
20+
collection_is_never_read = "warn"
21+
option_if_let_else = "warn"
22+
redundant_pub_crate = "warn"
23+
use_self = "warn"
24+
# noisy pedantic lints to allow
25+
module_name_repetitions = "allow"
26+
must_use_candidate = "allow"
27+
missing_errors_doc = "allow"
28+
missing_panics_doc = "allow"
29+
doc_markdown = "allow"
30+
31+
[workspace.lints.rust]
32+
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] }

crates/vespera/Cargo.toml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
[package]
22
name = "vespera"
3-
version = "0.1.33"
4-
edition = "2024"
3+
version.workspace = true
4+
edition.workspace = true
55
description = "A fully automated OpenAPI engine for Axum with zero-config route and schema discovery"
6-
license = "Apache-2.0"
7-
repository = "https://github.com/dev-five-git/vespera"
8-
readme = "../../README.md"
6+
license.workspace = true
7+
repository.workspace = true
98

109
[features]
1110
default = ["dep:axum-extra", "axum-extra/typed-header", "axum-extra/form", "axum-extra/query", "axum-extra/multipart", "axum-extra/cookie"]
@@ -21,3 +20,6 @@ tempfile = "3"
2120
serde_json = "1"
2221
tower-layer = "0.3"
2322
tower-service = "0.3"
23+
24+
[lints]
25+
workspace = true

crates/vespera/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
//! Vespera - OpenAPI generation for Rust web frameworks
1+
//! Vespera - `OpenAPI` generation for Rust web frameworks
22
//!
3-
//! This crate provides macros and utilities for generating OpenAPI documentation
3+
//! This crate provides macros and utilities for generating `OpenAPI` documentation
44
//! from your route definitions.
55
66
// Re-export vespera_core types so users don't need to depend on vespera_core directly
@@ -66,7 +66,8 @@ impl<S> VesperaRouter<S>
6666
where
6767
S: Clone + Send + Sync + 'static,
6868
{
69-
/// Create a new VesperaRouter with a base router and routers to merge
69+
/// Create a new `VesperaRouter` with a base router and routers to merge
70+
#[must_use]
7071
pub fn new(base: axum::Router<S>, merge_fns: Vec<fn() -> axum::Router<()>>) -> Self {
7172
Self { base, merge_fns }
7273
}
@@ -92,6 +93,7 @@ where
9293
}
9394

9495
/// Add a layer to the router.
96+
#[must_use]
9597
pub fn layer<L>(self, layer: L) -> Self
9698
where
9799
L: tower_layer::Layer<axum::routing::Route> + Clone + Send + Sync + 'static,

crates/vespera_core/Cargo.toml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
[package]
22
name = "vespera_core"
3-
version = "0.1.33"
4-
edition = "2024"
3+
version.workspace = true
4+
edition.workspace = true
55
description = "Core types and utilities for Vespera"
6-
license = "Apache-2.0"
7-
repository = "https://github.com/dev-five-git/vespera"
8-
readme = "../../README.md"
6+
license.workspace = true
7+
repository.workspace = true
98

109
[dependencies]
1110
serde = { version = "1.0", features = ["derive"] }
1211
serde_json = "1.0"
1312

1413
[dev-dependencies]
15-
rstest = "0.26"
14+
rstest = "0.26"
15+
16+
[lints]
17+
workspace = true

crates/vespera_core/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
//! Vespera Core - OpenAPI structure definitions
1+
//! Vespera Core - `OpenAPI` structure definitions
22
//!
3-
//! Provides structures conforming to the OpenAPI 3.1 specification.
3+
//! Provides structures conforming to the `OpenAPI` 3.1 specification.
44
55
pub mod openapi;
66
pub mod route;

crates/vespera_core/src/openapi.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
//! OpenAPI document structure definitions
1+
//! `OpenAPI` document structure definitions
22
33
use crate::route::PathItem;
44
use crate::schema::{Components, ExternalDocumentation};
55
use serde::{Deserialize, Serialize};
66
use std::collections::{BTreeMap, HashMap};
77

8-
/// OpenAPI document version
8+
/// `OpenAPI` document version
99
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1010
pub enum OpenApiVersion {
1111
#[serde(rename = "3.0.0")]
@@ -114,11 +114,11 @@ pub struct Tag {
114114
pub external_docs: Option<ExternalDocumentation>,
115115
}
116116

117-
/// OpenAPI document (root structure)
117+
/// `OpenAPI` document (root structure)
118118
#[derive(Debug, Clone, Serialize, Deserialize)]
119119
#[serde(rename_all = "camelCase")]
120120
pub struct OpenApi {
121-
/// OpenAPI version
121+
/// `OpenAPI` version
122122
pub openapi: OpenApiVersion,
123123
/// API information
124124
pub info: Info,
@@ -142,10 +142,10 @@ pub struct OpenApi {
142142
}
143143

144144
impl OpenApi {
145-
/// Merge another OpenAPI document into this one.
145+
/// Merge another `OpenAPI` document into this one.
146146
/// Paths, schemas, and tags from `other` are added to `self`.
147147
/// If there are conflicts, `self` takes precedence.
148-
pub fn merge(&mut self, other: OpenApi) {
148+
pub fn merge(&mut self, other: Self) {
149149
// Merge paths (self takes precedence on conflict)
150150
for (path, item) in other.paths {
151151
self.paths.entry(path).or_insert(item);
@@ -194,8 +194,13 @@ impl OpenApi {
194194
}
195195

196196
/// Merge from a JSON string. Returns error if parsing fails.
197+
///
198+
/// # Errors
199+
///
200+
/// Returns a `serde_json::Error` when `json_str` is not valid JSON or does not
201+
/// deserialize into an `OpenApi` document.
197202
pub fn merge_from_str(&mut self, json_str: &str) -> Result<(), serde_json::Error> {
198-
let other: OpenApi = serde_json::from_str(json_str)?;
203+
let other: Self = serde_json::from_str(json_str)?;
199204
self.merge(other);
200205
Ok(())
201206
}

crates/vespera_core/src/route.rs

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::collections::{BTreeMap, HashMap};
66
use crate::SchemaRef;
77

88
/// HTTP method
9-
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
9+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1010
#[serde(rename_all = "UPPERCASE")]
1111
pub enum HttpMethod {
1212
Get,
@@ -19,18 +19,35 @@ pub enum HttpMethod {
1919
Trace,
2020
}
2121

22-
impl From<&str> for HttpMethod {
23-
fn from(value: &str) -> Self {
22+
impl std::fmt::Display for HttpMethod {
23+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24+
match self {
25+
Self::Get => write!(f, "GET"),
26+
Self::Post => write!(f, "POST"),
27+
Self::Put => write!(f, "PUT"),
28+
Self::Patch => write!(f, "PATCH"),
29+
Self::Delete => write!(f, "DELETE"),
30+
Self::Head => write!(f, "HEAD"),
31+
Self::Options => write!(f, "OPTIONS"),
32+
Self::Trace => write!(f, "TRACE"),
33+
}
34+
}
35+
}
36+
37+
impl TryFrom<&str> for HttpMethod {
38+
type Error = String;
39+
40+
fn try_from(value: &str) -> Result<Self, Self::Error> {
2441
match value.to_uppercase().as_str() {
25-
"GET" => HttpMethod::Get,
26-
"POST" => HttpMethod::Post,
27-
"PUT" => HttpMethod::Put,
28-
"PATCH" => HttpMethod::Patch,
29-
"DELETE" => HttpMethod::Delete,
30-
"HEAD" => HttpMethod::Head,
31-
"OPTIONS" => HttpMethod::Options,
32-
"TRACE" => HttpMethod::Trace,
33-
_ => HttpMethod::Get, // default value
42+
"GET" => Ok(Self::Get),
43+
"POST" => Ok(Self::Post),
44+
"PUT" => Ok(Self::Put),
45+
"PATCH" => Ok(Self::Patch),
46+
"DELETE" => Ok(Self::Delete),
47+
"HEAD" => Ok(Self::Head),
48+
"OPTIONS" => Ok(Self::Options),
49+
"TRACE" => Ok(Self::Trace),
50+
other => Err(format!("unknown HTTP method: {other}")),
3451
}
3552
}
3653
}
@@ -137,7 +154,7 @@ pub struct Header {
137154
pub schema: Option<SchemaRef>,
138155
}
139156

140-
/// OpenAPI Operation definition
157+
/// `OpenAPI` Operation definition
141158
#[derive(Debug, Clone, Serialize, Deserialize)]
142159
#[serde(rename_all = "camelCase")]
143160
pub struct Operation {
@@ -221,7 +238,8 @@ impl PathItem {
221238
}
222239

223240
/// Get an operation for a specific HTTP method
224-
pub fn get_operation(&self, method: &HttpMethod) -> Option<&Operation> {
241+
#[must_use]
242+
pub const fn get_operation(&self, method: &HttpMethod) -> Option<&Operation> {
225243
match method {
226244
HttpMethod::Get => self.get.as_ref(),
227245
HttpMethod::Post => self.post.as_ref(),
@@ -277,15 +295,14 @@ mod tests {
277295
#[case("trace", HttpMethod::Trace)]
278296
#[case("Trace", HttpMethod::Trace)]
279297
fn test_http_method_from_str(#[case] input: &str, #[case] expected: HttpMethod) {
280-
let result = HttpMethod::from(input);
298+
let result = HttpMethod::try_from(input).unwrap();
281299
assert_eq!(result, expected);
282300
}
283301

284302
#[test]
285303
fn test_http_method_from_invalid_str() {
286-
// Invalid method should default to Get
287-
let result = HttpMethod::from("INVALID");
288-
assert_eq!(result, HttpMethod::Get);
304+
let result = HttpMethod::try_from("INVALID");
305+
assert!(result.is_err());
289306
}
290307

291308
#[test]
@@ -523,6 +540,19 @@ mod tests {
523540
);
524541
}
525542

543+
#[rstest]
544+
#[case(HttpMethod::Get, "GET")]
545+
#[case(HttpMethod::Post, "POST")]
546+
#[case(HttpMethod::Put, "PUT")]
547+
#[case(HttpMethod::Patch, "PATCH")]
548+
#[case(HttpMethod::Delete, "DELETE")]
549+
#[case(HttpMethod::Head, "HEAD")]
550+
#[case(HttpMethod::Options, "OPTIONS")]
551+
#[case(HttpMethod::Trace, "TRACE")]
552+
fn test_http_method_display(#[case] method: HttpMethod, #[case] expected: &str) {
553+
assert_eq!(method.to_string(), expected);
554+
}
555+
526556
#[test]
527557
fn test_http_method_equality() {
528558
let method1 = HttpMethod::Get;
@@ -536,7 +566,7 @@ mod tests {
536566
#[test]
537567
fn test_http_method_clone() {
538568
let method = HttpMethod::Get;
539-
let cloned = method.clone();
569+
let cloned = method;
540570
assert_eq!(method, cloned);
541571
}
542572

0 commit comments

Comments
 (0)