Reformat Rust code

This commit is contained in:
2025-03-06 11:37:22 +01:00
parent cb964988d4
commit f060f11ba5
2 changed files with 150 additions and 126 deletions

View File

@@ -1,6 +1,11 @@
<component name="InspectionProjectProfileManager"> <component name="InspectionProjectProfileManager">
<profile version="1.0"> <profile version="1.0">
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="54" name="Rust" />
</Languages>
</inspection_tool>
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" /> <option name="processCode" value="true" />
<option name="processLiterals" value="true" /> <option name="processLiterals" value="true" />

View File

@@ -1,35 +1,39 @@
use diesel::prelude::*; use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, Result, Context};
use askama_axum::Template; use askama_axum::Template;
use axum::{extract::{Path, State}, http::{Method, header, StatusCode, Request, Uri}, response::{IntoResponse, Response, Html}, routing::{get, post}, Json, Router, Form, http};
use axum::http::HeaderValue; use axum::http::HeaderValue;
use deadpool_diesel::sqlite::{Runtime, Manager, Pool}; use axum::{
extract::{Path, State},
http,
http::{header, Method, Request, StatusCode, Uri},
response::{Html, IntoResponse, Response},
routing::{get, post},
Form, Json, Router,
};
use clap::Parser; use clap::Parser;
use tower::{ServiceBuilder}; use deadpool_diesel::sqlite::{Manager, Pool, Runtime};
use diesel::prelude::*;
use serde::Deserialize;
use tower::ServiceBuilder;
use tower_http::{ use tower_http::{
cors::{Any, CorsLayer}, cors::{Any, CorsLayer},
trace::{TraceLayer, DefaultOnResponse},
services::ServeDir, services::ServeDir,
LatencyUnit trace::{DefaultOnResponse, TraceLayer},
}; LatencyUnit,
use serde::Deserialize;
use tracing::{
info, error, debug, info_span, enabled,
instrument, Level, Span
}; };
use tracing::{debug, enabled, error, info, info_span, instrument, Level, Span};
pub mod models; pub mod models;
pub mod schema; pub mod schema;
use self::models::*; use self::models::*;
#[derive(Parser,Clone)] #[derive(Parser, Clone)]
struct Config { struct Config {
#[arg(long,env)] #[arg(long, env)]
database_url: String, database_url: String,
#[arg(long,env)] #[arg(long, env)]
http_host: String, http_host: String,
#[arg(long,env)] #[arg(long, env)]
http_port: u16, http_port: u16,
} }
@@ -41,10 +45,7 @@ struct AppContext {
async fn establish_connection(database_url: &str) -> Pool { async fn establish_connection(database_url: &str) -> Pool {
let manager = Manager::new(database_url, Runtime::Tokio1); let manager = Manager::new(database_url, Runtime::Tokio1);
let pool = Pool::builder(manager) let pool = Pool::builder(manager).max_size(8).build().unwrap();
.max_size(8)
.build()
.unwrap();
let _ = pool.get().await.expect("DB connection failed"); // Test if DB connection was fine let _ = pool.get().await.expect("DB connection failed"); // Test if DB connection was fine
pool pool
} }
@@ -82,10 +83,9 @@ async fn main() -> Result<()> {
.on_response( .on_response(
DefaultOnResponse::new() DefaultOnResponse::new()
.level(Level::DEBUG) .level(Level::DEBUG)
.latency_unit(LatencyUnit::Millis) .latency_unit(LatencyUnit::Millis),
); );
let middlewares = ServiceBuilder::new() let middlewares = ServiceBuilder::new().layer(tracelayer).layer(cors);
.layer(tracelayer).layer(cors);
// Launch Web Server // Launch Web Server
let app = Router::new() let app = Router::new()
// TODO: Serve a mano di favicon // TODO: Serve a mano di favicon
@@ -100,190 +100,211 @@ async fn main() -> Result<()> {
.with_state(context.clone()); .with_state(context.clone());
// Run our app with hyper // Run our app with hyper
let listener = tokio::net::TcpListener::bind((config.http_host.as_str(), config.http_port)) let listener = tokio::net::TcpListener::bind((config.http_host.as_str(), config.http_port))
.await.context(format!("Failed to bind Web Service on {}:{}", config.http_host, config.http_port))?; .await
.context(format!(
"Failed to bind Web Service on {}:{}",
config.http_host, config.http_port
))?;
info!("Listening on {}:{}", config.http_host, config.http_port); info!("Listening on {}:{}", config.http_host, config.http_port);
axum::serve(listener, app).await.context("Failed to serve Web Service")?; axum::serve(listener, app)
.await
.context("Failed to serve Web Service")?;
Ok(()) Ok(())
} }
#[derive(Template)] #[derive(Template)]
#[template(path="feed.html")] #[template(path = "feed.html")]
struct FeedTemplate { struct FeedTemplate {
feed: RssFeed feed: RssFeed,
} }
async fn get_feed( async fn get_feed(State(ctx): State<AppContext>, Path(feed_id): Path<i32>) -> FeedTemplate {
State(ctx): State<AppContext>,
Path(feed_id): Path<i32>
) -> FeedTemplate {
let conn = ctx.pool.get().await.unwrap(); let conn = ctx.pool.get().await.unwrap();
use self::schema::rss_feeds::dsl::*; use self::schema::rss_feeds::dsl::*;
let result = conn.interact(move |conn| { let result = conn
.interact(move |conn| {
rss_feeds rss_feeds
.find(feed_id) .find(feed_id)
.select(RssFeed::as_select()) .select(RssFeed::as_select())
.first(conn) .first(conn)
.optional() .optional()
.expect("Error loading feeds") .expect("Error loading feeds")
}).await.unwrap(); })
.await
.unwrap();
if let Some(feed) = result { if let Some(feed) = result {
FeedTemplate{ feed } FeedTemplate { feed }
} else { } else {
FeedTemplate{ FeedTemplate {
feed: RssFeed{ feed: RssFeed {
id: -1, id: -1,
name: "ERROR".to_string(), name: "ERROR".to_string(),
feed_url: "ERROR".to_string(), feed_url: "ERROR".to_string(),
last_pub_date: Some("ERROR".to_string()) last_pub_date: Some("ERROR".to_string()),
} },
} }
} }
} }
#[derive(Template)] #[derive(Template)]
#[template(path="feed_form.html")] #[template(path = "feed_form.html")]
struct FeedFormTemplate { struct FeedFormTemplate {
feed: RssFeed feed: RssFeed,
} }
async fn get_feed_form( async fn get_feed_form(
State(ctx): State<AppContext>, State(ctx): State<AppContext>,
Path(feed_id): Path<i32> Path(feed_id): Path<i32>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let conn = ctx.pool.get().await.unwrap(); let conn = ctx.pool.get().await.unwrap();
use self::schema::rss_feeds::dsl::*; use self::schema::rss_feeds::dsl::*;
let result = conn.interact(move |conn| { let result = conn
.interact(move |conn| {
rss_feeds rss_feeds
.find(feed_id) .find(feed_id)
.select(RssFeed::as_select()) .select(RssFeed::as_select())
.first(conn) .first(conn)
.optional() .optional()
.expect("Error loading feeds") .expect("Error loading feeds")
}).await.unwrap(); })
.await
.unwrap();
if let Some(feed) = result { if let Some(feed) = result {
FeedFormTemplate{ feed } FeedFormTemplate { feed }
} else { } else {
FeedFormTemplate{ FeedFormTemplate {
feed: RssFeed{ feed: RssFeed {
id: -1, id: -1,
name: "ERROR".to_string(), name: "ERROR".to_string(),
feed_url: "ERROR".to_string(), feed_url: "ERROR".to_string(),
last_pub_date: Some("ERROR".to_string()) last_pub_date: Some("ERROR".to_string()),
} },
} }
} }
} }
#[derive(Template)] #[derive(Template)]
#[template(path="feed_inline.html")] #[template(path = "feed_inline.html")]
struct FeedInlineTemplate { struct FeedInlineTemplate {
feed: RssFeed feed: RssFeed,
} }
async fn get_feed_inline( async fn get_feed_inline(
State(ctx): State<AppContext>, State(ctx): State<AppContext>,
Path(feed_id): Path<i32> Path(feed_id): Path<i32>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let conn = ctx.pool.get().await.unwrap(); let conn = ctx.pool.get().await.unwrap();
use self::schema::rss_feeds::dsl::*; use self::schema::rss_feeds::dsl::*;
let result = conn.interact(move |conn| { let result = conn
.interact(move |conn| {
rss_feeds rss_feeds
.find(feed_id) .find(feed_id)
.select(RssFeed::as_select()) .select(RssFeed::as_select())
.first(conn) .first(conn)
.optional() .optional()
.expect("Error loading feeds") .expect("Error loading feeds")
}).await.unwrap(); })
.await
.unwrap();
if let Some(feed) = result { if let Some(feed) = result {
FeedInlineTemplate{ feed } FeedInlineTemplate { feed }
} else { } else {
FeedInlineTemplate{ FeedInlineTemplate {
feed: RssFeed{ feed: RssFeed {
id: -1, id: -1,
name: "ERROR".to_string(), name: "ERROR".to_string(),
feed_url: "ERROR".to_string(), feed_url: "ERROR".to_string(),
last_pub_date: Some("ERROR".to_string()) last_pub_date: Some("ERROR".to_string()),
} },
} }
} }
} }
#[derive(Deserialize, AsChangeset)] #[derive(Deserialize, AsChangeset)]
#[diesel(table_name = crate::schema::rss_feeds)] #[diesel(table_name = crate::schema::rss_feeds)]
struct PostForm{ struct PostForm {
name: String, name: String,
feed_url: String, feed_url: String,
} }
async fn post_feed( async fn post_feed(State(ctx): State<AppContext>, Form(post): Form<PostForm>) -> impl IntoResponse {
State(ctx): State<AppContext>,
Form(post): Form<PostForm>,
) -> impl IntoResponse {
let conn = ctx.pool.get().await.unwrap(); let conn = ctx.pool.get().await.unwrap();
use self::schema::rss_feeds::dsl::*; use self::schema::rss_feeds::dsl::*;
let result = conn.interact(move |conn| { let result = conn
let new_feed = NewRssFeed{name: post.name.as_str(), feed_url: post.feed_url.as_str() }; .interact(move |conn| {
let new_feed = NewRssFeed {
name: post.name.as_str(),
feed_url: post.feed_url.as_str(),
};
diesel::insert_into(rss_feeds) diesel::insert_into(rss_feeds)
.values(&new_feed) .values(&new_feed)
.returning(RssFeed::as_select()) .returning(RssFeed::as_select())
.get_result(conn) .get_result(conn)
.expect("Error saving new feed") .expect("Error saving new feed")
}).await.unwrap(); })
FeedTemplate{ feed: result } .await
.unwrap();
FeedTemplate { feed: result }
} }
async fn put_feed( async fn put_feed(
State(ctx): State<AppContext>, State(ctx): State<AppContext>,
Path(feed_id): Path<i32>, Path(feed_id): Path<i32>,
Form(post): Form<PostForm> Form(post): Form<PostForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let conn = ctx.pool.get().await.unwrap(); let conn = ctx.pool.get().await.unwrap();
use self::schema::rss_feeds::dsl::*; use self::schema::rss_feeds::dsl::*;
let result = conn.interact(move |conn| { let result = conn
.interact(move |conn| {
diesel::update(rss_feeds.find(feed_id)) diesel::update(rss_feeds.find(feed_id))
.set(post) .set(post)
.returning(RssFeed::as_select()) .returning(RssFeed::as_select())
.get_result(conn) .get_result(conn)
.expect("Error updating feed") .expect("Error updating feed")
}).await.unwrap(); })
FeedTemplate{ feed: result } .await
.unwrap();
FeedTemplate { feed: result }
} }
#[derive(Template)] #[derive(Template)]
#[template(source="\ #[template(
source = "\
{% for feed in feeds %} {% for feed in feeds %}
{% include \"feed.html\" %} {% include \"feed.html\" %}
{% endfor %}", ext="html")] {% endfor %}",
ext = "html"
)]
struct FeedsTemplate { struct FeedsTemplate {
feeds: Vec<RssFeed> feeds: Vec<RssFeed>,
} }
async fn get_list_feed( async fn get_list_feed(State(ctx): State<AppContext>) -> FeedsTemplate {
State(ctx): State<AppContext>,
) -> FeedsTemplate {
let conn = ctx.pool.get().await.unwrap(); let conn = ctx.pool.get().await.unwrap();
use self::schema::rss_feeds::dsl::*; use self::schema::rss_feeds::dsl::*;
let result = conn.interact(|conn| { let result = conn
.interact(|conn| {
rss_feeds rss_feeds
.select(RssFeed::as_select()) .select(RssFeed::as_select())
.load(conn) .load(conn)
.expect("Error loading feeds") .expect("Error loading feeds")
}).await.unwrap(); })
FeedsTemplate{ feeds: result } .await
.unwrap();
FeedsTemplate { feeds: result }
} }
async fn delete_feed( async fn delete_feed(State(ctx): State<AppContext>, Path(feed_id): Path<i32>) -> impl IntoResponse {
State(ctx): State<AppContext>,
Path(feed_id): Path<i32>,
) -> impl IntoResponse {
let conn = ctx.pool.get().await.unwrap(); let conn = ctx.pool.get().await.unwrap();
use self::schema::rss_feeds::dsl::*; use self::schema::rss_feeds::dsl::*;
let num_deleted = conn.interact(move |conn| { let num_deleted = conn
.interact(move |conn| {
diesel::delete(rss_feeds.find(feed_id)) diesel::delete(rss_feeds.find(feed_id))
.execute(conn) .execute(conn)
.expect("Error deleting posts") .expect("Error deleting posts")
}).await.unwrap(); })
.await
.unwrap();
if num_deleted == 0 { if num_deleted == 0 {
(StatusCode::NOT_FOUND, "Not found") (StatusCode::NOT_FOUND, "Not found")
} else { } else {
@@ -296,12 +317,10 @@ async fn delete_feed(
#[derive(Template)] #[derive(Template)]
#[template(path = "index.html")] #[template(path = "index.html")]
struct IndexTemplate { struct IndexTemplate {
feeds: FeedsTemplate feeds: FeedsTemplate,
} }
async fn index( async fn index(State(ctx): State<AppContext>) -> IndexTemplate {
State(ctx): State<AppContext>,
) -> IndexTemplate {
let feeds = get_list_feed(State(ctx)).await; let feeds = get_list_feed(State(ctx)).await;
IndexTemplate { feeds } IndexTemplate { feeds }
} }