some more docs

This commit is contained in:
Sebastian Hugentobler 2025-07-02 21:57:44 +02:00
parent 1314320260
commit 41206abac1
Signed by: shu
SSH key fingerprint: SHA256:ppcx6MlixdNZd5EUM1nkHOKoyQYoJwzuQKXM6J/t66M
29 changed files with 119 additions and 0 deletions

View file

@ -283,6 +283,7 @@ impl Calibre {
}
#[cfg(test)]
/// Tests for the calibre module.
mod tests {
use super::*;

View file

@ -1,3 +1,4 @@
//! Data types and functions for interacting with the calibre database.
pub mod author;
pub mod book;
pub mod error;

View file

@ -24,17 +24,23 @@ pub struct MultipleAuthorsError {
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching a book's author.
pub enum BookAuthorError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareBookAuthor { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteBookAuthor { source: rusqlite::Error },
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching a single author.
pub enum ScalarAuthorError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareScalarAuthor { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteScalarAuthor { source: rusqlite::Error },
}
@ -52,6 +58,7 @@ pub struct MoreAuthorsError {
}
impl Author {
/// Create an author from a database row.
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
Ok(Self {
id: row.get(0)?,

View file

@ -39,25 +39,34 @@ pub struct AuthorBooksError {
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching a series' books.
pub enum SeriesBookError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareSeriesBook { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteSeriesBook { source: rusqlite::Error },
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching recent books.
pub enum RecentBooksError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareRecentBooks { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteRecentBooks { source: rusqlite::Error },
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching a single book.
pub enum ScalarBookError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareScalarBook { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteScalarBook { source: rusqlite::Error },
}
@ -75,6 +84,7 @@ pub struct MoreBooksError {
}
impl Book {
/// Create a book from a database row.
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
Ok(Self {
id: row.get(0)?,

View file

@ -24,17 +24,23 @@ pub struct MultiplSeriesError {
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching a series' books.
pub enum SeriesBooksError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareSeriesBooks { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteSeriesBooks { source: rusqlite::Error },
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching a single series.
pub enum ScalarSeriesError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareScalarSeries { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteScalarSeries { source: rusqlite::Error },
}
@ -52,6 +58,7 @@ pub struct MoreSeriesError {
}
impl Series {
/// Create a series from a database row.
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
Ok(Self {
id: row.get(0)?,

View file

@ -35,39 +35,54 @@ const SEARCH_INIT_QUERY: &str = "INSERT INTO search.fts(book_id, data)
GROUP BY b.id";
#[derive(Debug, Snafu)]
/// Errors that can occur when ensuring the search database is available.
pub enum EnsureSearchDbError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareEnsureSearch { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteEnsureSearch { source: rusqlite::Error },
/// A failure to attach the database.
#[snafu(display("Failed to attach database."))]
Attach { source: AttachError },
/// A failure to initialize the database.
#[snafu(display("Failed to initialize database."))]
Init { source: InitError },
}
#[derive(Debug, Snafu)]
/// Errors that can occur when attaching the search database.
pub enum AttachError {
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteAttach { source: rusqlite::Error },
}
#[derive(Debug, Snafu)]
/// Errors that can occur when initializing the search database.
pub enum InitError {
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareInit { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteInit { source: rusqlite::Error },
}
#[derive(Debug, Snafu)]
/// Errors that can occur when searching.
pub enum SearchError {
/// A failure to ensure the search database is initialized.
#[snafu(display("Failed ensure the search db is initialized."))]
EnsureDb { source: EnsureSearchDbError },
/// A failure to get a connection from the pool.
#[snafu(display("Failed to get connection from pool."))]
Connection { source: r2d2::Error },
/// A failure to prepare the SQL statement.
#[snafu(display("Failed to prepare statement."))]
PrepareSearch { source: rusqlite::Error },
/// A failure to execute the SQL statement.
#[snafu(display("Failed to execute statement."))]
ExecuteSearch { source: rusqlite::Error },
}

View file

@ -8,6 +8,7 @@ use std::{
use ignore::Walk;
use zip::{CompressionMethod, write::SimpleFileOptions};
/// Create a zip archive of the source code.
fn main() -> Result<(), Box<dyn std::error::Error>> {
let out_dir = env::var("OUT_DIR")?;
let src_dir = "..";

View file

@ -30,6 +30,7 @@ pub enum SortOrder {
}
impl From<SortOrder> for calibre_db::data::pagination::SortOrder {
/// Convert the API sort order to the database sort order.
fn from(val: SortOrder) -> Self {
match val {
SortOrder::ASC => calibre_db::data::pagination::SortOrder::ASC,

View file

@ -10,13 +10,17 @@ use super::SortOrder;
use crate::data::book::Book;
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving a single author.
pub enum SingleAuthorError {
/// A failure to fetch author data.
#[snafu(display("Failed to fetch author data."))]
AuthorData { source: DataStoreError },
/// A failure to fetch books from the author.
#[snafu(display("Failed to fetch books from author."))]
BookData { source: DataStoreError },
}
/// Retrieve a single author and all their books.
pub async fn single(
id: u64,
calibre: &Calibre,

View file

@ -6,11 +6,14 @@ use snafu::{ResultExt, Snafu};
use crate::data::book::Book;
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching recent books.
pub enum RecentBooksError {
/// A failure to fetch recent books.
#[snafu(display("Failed to fetch recent books."))]
RecentBooks { source: DataStoreError },
}
/// Fetch recent books and enrich them with additional information.
pub async fn recent(calibre: &Calibre, library_path: &Path) -> Result<Vec<Book>, RecentBooksError> {
let recent_books = calibre.recent_books(25).context(RecentBooksSnafu)?;
let recent_books = recent_books

View file

@ -1,3 +1,4 @@
//! Handlers for HTML responses.
pub mod archive;
pub mod authors;
pub mod books;

View file

@ -14,7 +14,9 @@ use crate::{
const SOURCE_ARCHIVE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/archive.zip"));
#[derive(Debug, Snafu)]
/// Errors that can occur when downloading the source code archive.
pub enum ArchiveError {
/// A failure to stream the source code archive.
#[snafu(display("Failed to stream source code archive."))]
Download { source: DownloadError },
}

View file

@ -21,7 +21,9 @@ use crate::{
};
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving authors.
pub enum RetrieveError {
/// A failure to fetch pagination data.
#[snafu(display("Failed to fetch pagination data."))]
Authors { source: AuthorError },
}
@ -68,11 +70,14 @@ pub async fn handler(
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching an author.
pub enum AuthorError {
/// A failure to fetch pagination data.
#[snafu(display("Failed to fetch pagination data."))]
Pagination { source: PaginationError },
}
/// Render a paginated list of authors.
async fn authors(
state: &Arc<AppState>,
cursor: Option<&str>,
@ -89,9 +94,12 @@ async fn authors(
}
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving a single author.
pub enum SingleError {
/// A failure to fetch author data.
#[snafu(display("Failed to fetch author data."))]
Data { source: SingleAuthorError },
/// A failure to render the template.
#[snafu(display("Failed to render template."))]
Render { source: tera::Error },
}

View file

@ -39,6 +39,7 @@ impl HttpStatus for SearchError {
http_error!(SearchError);
#[derive(Deserialize)]
/// Parameters for a search request.
pub struct Params {
/// Query for a search request.
query: String,

View file

@ -21,7 +21,9 @@ use crate::{
};
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving series.
pub enum RetrieveError {
/// A failure to fetch series data.
#[snafu(display("Failed to fetch series data."))]
Series { source: SeriesError },
}
@ -68,11 +70,14 @@ pub async fn handler(
}
#[derive(Debug, Snafu)]
/// Errors that can occur when fetching a series.
pub enum SeriesError {
/// A failure to fetch pagination data.
#[snafu(display("Failed to fetch pagination data."))]
Pagination { source: PaginationError },
}
/// Render a paginated list of series.
async fn series(
state: &Arc<AppState>,
cursor: Option<&str>,
@ -89,9 +94,12 @@ async fn series(
}
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving a single series.
pub enum SingleError {
/// A failure to fetch series data.
#[snafu(display("Failed to fetch series data."))]
Data { source: SingleSeriesError },
/// A failure to render the template.
#[snafu(display("Failed to render template."))]
Render { source: tera::Error },
}

View file

@ -1,3 +1,4 @@
//! Handlers for OPDS feeds.
pub mod authors;
pub mod books;
pub mod recent;

View file

@ -25,9 +25,12 @@ use crate::{
};
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving all authors.
pub enum AuthorsError {
/// A failure to fetch author data.
#[snafu(display("Failed to fetch author data."))]
Data { source: DataStoreError },
/// A failure to render author data.
#[snafu(display("Failed to render author data."))]
Render { source: AsXmlError },
}
@ -81,9 +84,12 @@ pub async fn handler(State(state): State<Arc<AppState>>) -> Result<Response, Aut
}
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving a single author.
pub enum SingleError {
/// A failure to fetch author data.
#[snafu(display("Failed to fetch author data."))]
AuthorData { source: SingleAuthorError },
/// A failure to render the feed.
#[snafu(display("Failed to render feed."))]
FeedRender { source: AsXmlError },
}

View file

@ -25,9 +25,12 @@ use crate::{
};
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving books for OPDS.
pub enum OdpsBooksError {
/// A failure to fetch book data.
#[snafu(display("Failed to fetch book data."))]
Data { source: DataStoreError },
/// A failure to render book data.
#[snafu(display("Failed to render book data."))]
Render { source: RenderError },
}
@ -65,7 +68,9 @@ pub async fn handler(State(state): State<Arc<AppState>>) -> Result<Response, Odp
}
#[derive(Debug, Snafu)]
/// Errors that can occur when rendering a feed.
pub enum RenderError {
/// A failure to create the OPDS feed.
#[snafu(display("Failed to create opds feed."))]
Feed { source: AsXmlError },
}

View file

@ -24,9 +24,12 @@ use crate::{
};
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving recent books.
pub enum RecentError {
/// A failure to fetch recent books.
#[snafu(display("Failed to fetch recent books."))]
Data { source: RecentBooksError },
/// A failure to render the feed.
#[snafu(display("Failed to render feed."))]
Render { source: AsXmlError },
}

View file

@ -25,9 +25,12 @@ use crate::{
};
#[derive(Debug, Snafu)]
/// Errors that can occur when searching for books.
pub enum SearchError {
/// A failure to query for books.
#[snafu(display("Failed to query books."))]
Query { source: SearchQueryError },
/// A failure to render the feed.
#[snafu(display("Failed to render feed."))]
Render { source: RenderError },
}
@ -42,6 +45,7 @@ impl HttpStatus for SearchError {
http_error!(SearchError);
#[derive(Deserialize)]
/// Parameters for a search request.
pub struct Params {
/// Query for a search request.
query: String,
@ -67,7 +71,9 @@ pub async fn handler(
}
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving search information.
pub enum InfoError {
/// A failure to render the feed.
#[snafu(display("Failed to render feed."))]
FeedRender { source: AsXmlError },
}
@ -81,6 +87,7 @@ impl HttpStatus for InfoError {
http_error!(InfoError);
/// Render search information as an OPDS feed.
#[utoipa::path(
get,
path = "/search/info",

View file

@ -25,9 +25,12 @@ use crate::{
};
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving all series.
pub enum SeriesError {
/// A failure to fetch series data.
#[snafu(display("Failed to fetch series data."))]
Data { source: DataStoreError },
/// A failure to render series data.
#[snafu(display("Failed to render series data."))]
Render { source: AsXmlError },
}
@ -81,9 +84,12 @@ pub async fn handler(State(state): State<Arc<AppState>>) -> Result<Response, Ser
}
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving a single series.
pub enum SingleError {
/// A failure to fetch series data.
#[snafu(display("Failed to fetch series data."))]
SeriesData { source: SingleSeriesError },
/// A failure to render the feed.
#[snafu(display("Failed to render feed."))]
FeedRender { source: AsXmlError },
}

View file

@ -11,13 +11,18 @@ use tera::Context;
use crate::templates::TEMPLATES;
#[derive(Debug, Snafu)]
/// Errors that can occur during pagination.
pub enum PaginationError {
/// A failure to fetch pagination data.
#[snafu(display("Failed to fetch pagination data."))]
Fetch { source: DataStoreError },
/// A failure to render the template.
#[snafu(display("Failed to render template."))]
Template { source: tera::Error },
/// A failure to fetch previous items.
#[snafu(display("Failed to fetch previous items."))]
Previous { source: DataStoreError },
/// A failure to fetch more items.
#[snafu(display("Failed to fetch more items."))]
More { source: DataStoreError },
}

View file

View file

@ -6,11 +6,14 @@ use snafu::{ResultExt, Snafu};
use crate::data::book::Book;
#[derive(Debug, Snafu)]
/// Errors that can occur when querying for books.
pub enum SearchQueryError {
/// A failure to query the database.
#[snafu(display("Failed to search for books."))]
Db { source: DataStoreError },
}
/// Query for books and enrich them with additional information.
pub async fn query(
query: &str,
calibre: &Calibre,

View file

@ -9,13 +9,17 @@ use snafu::{ResultExt, Snafu};
use crate::data::book::Book;
#[derive(Debug, Snafu)]
/// Errors that can occur when retrieving a single series.
pub enum SingleSeriesError {
/// A failure to fetch series data.
#[snafu(display("Failed to fetch series data."))]
SeriesData { source: DataStoreError },
/// A failure to fetch books in the series.
#[snafu(display("Failed to fetch books in series."))]
BookData { source: DataStoreError },
}
/// Retrieve a single series and all its books.
pub async fn single(
id: u64,
calibre: &Calibre,

View file

@ -28,6 +28,7 @@ pub async fn handler(uri: Uri) -> impl IntoResponse {
StaticFile(path)
}
/// A wrapper type for static files.
pub struct StaticFile<T>(pub T);
impl<T> IntoResponse for StaticFile<T>

View file

@ -14,17 +14,22 @@ use crate::cli::Cli;
/// Errors from loading application configuration.
#[derive(Debug, Snafu)]
pub enum LoadError {
/// The provided path is not a calibre library.
#[snafu(display("{path} is not a calibre library."))]
LibraryPath { path: String },
/// Could not find the calibre metadata database.
#[snafu(display("Could not find calibre metadata at {path}."))]
MetadataPath { path: String },
/// The listening address could not be parsed.
#[snafu(display("Invalid listening address {listen_address}."))]
ListeningAddressParse {
source: io::Error,
listen_address: String,
},
/// The listening address is invalid.
#[snafu(display("Invalid listening address {listen_address}."))]
ListeningAddress { listen_address: String },
/// The cache directory could not be created.
#[snafu(display("Failed to create cach directory at {path}."))]
CacheDir { source: io::Error, path: String },
}

View file

@ -1 +1,2 @@
//! Data types and functions for enriching calibre data.
pub mod book;

View file

@ -17,8 +17,10 @@ use super::error::{
/// Url pointing to a location.
#[derive(Debug, Serialize)]
pub struct Url {
/// The media type of the resource.
#[serde(rename = "@type")]
pub type_name: String,
/// The URL template.
#[serde(rename = "@template")]
pub template: String,
}