bare bones calibre db reading
This commit is contained in:
commit
65e17fc55b
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
target
|
||||||
|
result
|
208
Cargo.lock
generated
Normal file
208
Cargo.lock
generated
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "calibre-db"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"rusqlite",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.96"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fallible-iterator"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fallible-streaming-iterator"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"allocator-api2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashlink"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "692eaaf7f7607518dd3cef090f1474b61edc5301d8012f09579920df68b725ee"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libsqlite3-sys"
|
||||||
|
version = "0.28.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.81"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.36"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rusqlite"
|
||||||
|
version = "0.31.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"fallible-iterator",
|
||||||
|
"fallible-streaming-iterator",
|
||||||
|
"hashlink",
|
||||||
|
"libsqlite3-sys",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.60"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.59"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.59"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
5
Cargo.toml
Normal file
5
Cargo.toml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
members = [
|
||||||
|
"calibre-db",
|
||||||
|
]
|
8
calibre-db/Cargo.toml
Normal file
8
calibre-db/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "calibre-db"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rusqlite = { version = "0.31.0", features = ["bundled"] }
|
||||||
|
thiserror = "1.0.59"
|
94
calibre-db/src/calibre.rs
Normal file
94
calibre-db/src/calibre.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
use rusqlite::Connection;
|
||||||
|
|
||||||
|
use crate::data::{author::Author, book::Book, error::DataStoreError, pagination::SortOrder};
|
||||||
|
|
||||||
|
pub struct Calibre {
|
||||||
|
conn: Connection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Calibre {
|
||||||
|
pub fn load(url: &str) -> Result<Self, DataStoreError> {
|
||||||
|
let conn = Connection::open(url)?;
|
||||||
|
Ok(Self { conn })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn books(
|
||||||
|
&self,
|
||||||
|
limit: u64,
|
||||||
|
cursor: Option<&str>,
|
||||||
|
sort_order: SortOrder,
|
||||||
|
) -> Result<Vec<Book>, DataStoreError> {
|
||||||
|
Book::books(&self.conn, limit, cursor, sort_order)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn authors(
|
||||||
|
&self,
|
||||||
|
limit: u64,
|
||||||
|
cursor: Option<&str>,
|
||||||
|
sort_order: SortOrder,
|
||||||
|
) -> Result<Vec<Author>, DataStoreError> {
|
||||||
|
Author::authors(&self.conn, limit, cursor, sort_order)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn author_books(
|
||||||
|
&self,
|
||||||
|
author_id: u64,
|
||||||
|
limit: u64,
|
||||||
|
cursor: Option<&str>,
|
||||||
|
sort_order: SortOrder,
|
||||||
|
) -> Result<Vec<Book>, DataStoreError> {
|
||||||
|
Book::author_books(&self.conn, author_id, limit, cursor, sort_order)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn books() {
|
||||||
|
let c = Calibre::load("./testdata/metadata.db").unwrap();
|
||||||
|
let books = c.books(10, None, SortOrder::ASC).unwrap();
|
||||||
|
assert_eq!(books.len(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn authors() {
|
||||||
|
let c = Calibre::load("./testdata/metadata.db").unwrap();
|
||||||
|
let authors = c.authors(10, None, SortOrder::ASC).unwrap();
|
||||||
|
assert_eq!(authors.len(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn author_books() {
|
||||||
|
let c = Calibre::load("./testdata/metadata.db").unwrap();
|
||||||
|
let books = c.author_books(1, 10, None, SortOrder::ASC).unwrap();
|
||||||
|
assert_eq!(books.len(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pagination() {
|
||||||
|
let c = Calibre::load("./testdata/metadata.db").unwrap();
|
||||||
|
let authors = c.authors(1, None, SortOrder::ASC).unwrap();
|
||||||
|
assert_eq!(authors.len(), 1);
|
||||||
|
assert_eq!(authors[0].name, "Kevin R. Grazier");
|
||||||
|
|
||||||
|
let authors = c
|
||||||
|
.authors(1, Some(&authors[0].sort), SortOrder::ASC)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(authors.len(), 1);
|
||||||
|
assert_eq!(authors[0].name, "Terry Pratchett");
|
||||||
|
|
||||||
|
let authors = c
|
||||||
|
.authors(1, Some(&authors[0].sort), SortOrder::ASC)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(authors.len(), 1);
|
||||||
|
assert_eq!(authors[0].name, "Edward Noyes Westcott");
|
||||||
|
|
||||||
|
let authors = c
|
||||||
|
.authors(1, Some(&authors[0].sort), SortOrder::DESC)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(authors.len(), 1);
|
||||||
|
assert_eq!(authors[0].name, "Terry Pratchett");
|
||||||
|
}
|
||||||
|
}
|
38
calibre-db/src/data/author.rs
Normal file
38
calibre-db/src/data/author.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use rusqlite::{Connection, Row};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
error::DataStoreError,
|
||||||
|
pagination::{Pagination, SortOrder},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Author {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
pub sort: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Author {
|
||||||
|
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
id: row.get(0)?,
|
||||||
|
name: row.get(1)?,
|
||||||
|
sort: row.get(2)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn authors(
|
||||||
|
conn: &Connection,
|
||||||
|
limit: u64,
|
||||||
|
cursor: Option<&str>,
|
||||||
|
sort_order: SortOrder,
|
||||||
|
) -> Result<Vec<Author>, DataStoreError> {
|
||||||
|
let pagination = Pagination::new("sort", cursor, limit, sort_order);
|
||||||
|
pagination.paginate(
|
||||||
|
conn,
|
||||||
|
"SELECT id, name, sort FROM authors",
|
||||||
|
&[],
|
||||||
|
Self::from_row,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
56
calibre-db/src/data/book.rs
Normal file
56
calibre-db/src/data/book.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use rusqlite::{Connection, Row};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
error::DataStoreError,
|
||||||
|
pagination::{Pagination, SortOrder},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Book {
|
||||||
|
pub id: i32,
|
||||||
|
pub title: String,
|
||||||
|
pub sort: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Book {
|
||||||
|
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
id: row.get(0)?,
|
||||||
|
title: row.get(1)?,
|
||||||
|
sort: row.get(2)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn books(
|
||||||
|
conn: &Connection,
|
||||||
|
limit: u64,
|
||||||
|
cursor: Option<&str>,
|
||||||
|
sort_order: SortOrder,
|
||||||
|
) -> Result<Vec<Book>, DataStoreError> {
|
||||||
|
let pagination = Pagination::new("sort", cursor, limit, sort_order);
|
||||||
|
pagination.paginate(
|
||||||
|
conn,
|
||||||
|
"SELECT id, title, sort FROM books",
|
||||||
|
&[],
|
||||||
|
Self::from_row,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn author_books(
|
||||||
|
conn: &Connection,
|
||||||
|
author_id: u64,
|
||||||
|
limit: u64,
|
||||||
|
cursor: Option<&str>,
|
||||||
|
sort_order: SortOrder,
|
||||||
|
) -> Result<Vec<Book>, DataStoreError> {
|
||||||
|
let pagination = Pagination::new("books.sort", cursor, limit, sort_order);
|
||||||
|
pagination.paginate(
|
||||||
|
conn,
|
||||||
|
"SELECT books.id, books.title, books.sort FROM books \
|
||||||
|
INNER JOIN books_authors_link ON books.id = books_authors_link.book \
|
||||||
|
WHERE books_authors_link.author = (:author_id) AND",
|
||||||
|
&[(":author_id", &author_id)],
|
||||||
|
Self::from_row,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
7
calibre-db/src/data/error.rs
Normal file
7
calibre-db/src/data/error.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum DataStoreError {
|
||||||
|
#[error("sqlite error")]
|
||||||
|
SqliteError(#[from] rusqlite::Error),
|
||||||
|
}
|
72
calibre-db/src/data/pagination.rs
Normal file
72
calibre-db/src/data/pagination.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
use rusqlite::{Connection, Row, ToSql};
|
||||||
|
|
||||||
|
use super::error::DataStoreError;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum SortOrder {
|
||||||
|
ASC,
|
||||||
|
DESC,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Pagination<'a> {
|
||||||
|
pub sort_col: &'a str,
|
||||||
|
pub limit: u64,
|
||||||
|
pub cursor: Option<&'a str>,
|
||||||
|
pub sort_order: SortOrder,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Pagination<'a> {
|
||||||
|
pub fn new(
|
||||||
|
sort_col: &'a str,
|
||||||
|
cursor: Option<&'a str>,
|
||||||
|
limit: u64,
|
||||||
|
sort_order: SortOrder,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
sort_col,
|
||||||
|
limit,
|
||||||
|
cursor,
|
||||||
|
sort_order,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paginate<T, F>(
|
||||||
|
&self,
|
||||||
|
conn: &Connection,
|
||||||
|
statement: &str,
|
||||||
|
params: &[(&str, &dyn ToSql)],
|
||||||
|
processor: F,
|
||||||
|
) -> Result<Vec<T>, DataStoreError>
|
||||||
|
where
|
||||||
|
F: FnMut(&Row<'_>) -> Result<T, rusqlite::Error>,
|
||||||
|
{
|
||||||
|
let cursor = self.cursor.unwrap_or("");
|
||||||
|
let comparison = if self.sort_order == SortOrder::ASC {
|
||||||
|
">"
|
||||||
|
} else {
|
||||||
|
"<"
|
||||||
|
};
|
||||||
|
let where_sql = if statement.ends_with("AND") {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
"WHERE"
|
||||||
|
};
|
||||||
|
|
||||||
|
let sort_col = self.sort_col;
|
||||||
|
let sort_order = &self.sort_order;
|
||||||
|
// DANGER: vulnerable to SQL injection if statement or sort_col variable is influenced by user input
|
||||||
|
let mut stmt = conn.prepare(&format!(
|
||||||
|
"{statement} {where_sql} {sort_col} {comparison} (:cursor) ORDER BY {sort_col} {sort_order:?} LIMIT (:limit)"
|
||||||
|
))?;
|
||||||
|
let params = [
|
||||||
|
&[
|
||||||
|
(":cursor", &cursor as &dyn ToSql),
|
||||||
|
(":limit", &self.limit as &dyn ToSql),
|
||||||
|
],
|
||||||
|
params,
|
||||||
|
]
|
||||||
|
.concat();
|
||||||
|
let iter = stmt.query_map(params.as_slice(), processor)?;
|
||||||
|
Ok(iter.filter_map(Result::ok).collect())
|
||||||
|
}
|
||||||
|
}
|
7
calibre-db/src/lib.rs
Normal file
7
calibre-db/src/lib.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
pub mod calibre;
|
||||||
|
pub mod data {
|
||||||
|
pub mod author;
|
||||||
|
pub mod book;
|
||||||
|
pub mod error;
|
||||||
|
pub mod pagination;
|
||||||
|
}
|
BIN
calibre-db/testdata/metadata.db
vendored
Normal file
BIN
calibre-db/testdata/metadata.db
vendored
Normal file
Binary file not shown.
145
flake.lock
Normal file
145
flake.lock
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1714544767,
|
||||||
|
"narHash": "sha256-kF1bX+YFMedf1g0PAJYwGUkzh22JmULtj8Rm4IXAQKs=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "73124e1356bde9411b163d636b39fe4804b7ca45",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1710146030,
|
||||||
|
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"naersk": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1713520724,
|
||||||
|
"narHash": "sha256-CO8MmVDmqZX2FovL75pu5BvwhW+Vugc7Q6ze7Hj8heI=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "naersk",
|
||||||
|
"rev": "c5037590290c6c7dae2e42e7da1e247e54ed2d49",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "naersk",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1714253743,
|
||||||
|
"narHash": "sha256-mdTQw2XlariysyScCv2tTE45QSU9v/ezLcHJ22f0Nxc=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "58a1abdbae3217ca6b702f03d3b35125d88a2994",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 0,
|
||||||
|
"narHash": "sha256-mdTQw2XlariysyScCv2tTE45QSU9v/ezLcHJ22f0Nxc=",
|
||||||
|
"path": "/nix/store/801l7gvdz7yaibhjsxqx82sc7zkakjbq-source",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_3": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1714253743,
|
||||||
|
"narHash": "sha256-mdTQw2XlariysyScCv2tTE45QSU9v/ezLcHJ22f0Nxc=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "58a1abdbae3217ca6b702f03d3b35125d88a2994",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"fenix": "fenix",
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"naersk": "naersk",
|
||||||
|
"nixpkgs": "nixpkgs_3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-analyzer-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1714501997,
|
||||||
|
"narHash": "sha256-g31zfxwUFzkPgX0Q8sZLcrqGmOxwjEZ/iqJjNx4fEGo=",
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"rev": "49e502b277a8126a9ad10c802d1aaa3ef1a280ef",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"ref": "nightly",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
148
flake.nix
Normal file
148
flake.nix
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
{
|
||||||
|
description = "rusty-cops project";
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
naersk.url = "github:nix-community/naersk";
|
||||||
|
fenix.url = "github:nix-community/fenix";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
naersk,
|
||||||
|
fenix,
|
||||||
|
flake-utils,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
buildTargets = {
|
||||||
|
"x86_64-linux" = {
|
||||||
|
crossSystemConfig = "x86_64-unknown-linux-musl";
|
||||||
|
rustTarget = "x86_64-unknown-linux-musl";
|
||||||
|
};
|
||||||
|
|
||||||
|
"i686-linux" = {
|
||||||
|
crossSystemConfig = "i686-unknown-linux-musl";
|
||||||
|
rustTarget = "i686-unknown-linux-musl";
|
||||||
|
};
|
||||||
|
|
||||||
|
"aarch64-linux" = {
|
||||||
|
crossSystemConfig = "aarch64-unknown-linux-musl";
|
||||||
|
rustTarget = "aarch64-unknown-linux-musl";
|
||||||
|
};
|
||||||
|
|
||||||
|
"armv6l-linux" = {
|
||||||
|
crossSystemConfig = "armv6l-unknown-linux-musleabihf";
|
||||||
|
rustTarget = "arm-unknown-linux-musleabihf";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
eachSystem =
|
||||||
|
supportedSystems: callback:
|
||||||
|
builtins.foldl' (overall: system: overall // { ${system} = callback system; }) { } supportedSystems;
|
||||||
|
|
||||||
|
eachCrossSystem =
|
||||||
|
supportedSystems: callback:
|
||||||
|
eachSystem supportedSystems (
|
||||||
|
buildSystem:
|
||||||
|
builtins.foldl' (
|
||||||
|
inner: targetSystem: inner // { "cross-${targetSystem}" = callback buildSystem targetSystem; }
|
||||||
|
) { default = callback buildSystem buildSystem; } supportedSystems
|
||||||
|
);
|
||||||
|
|
||||||
|
mkPkgs =
|
||||||
|
buildSystem: targetSystem:
|
||||||
|
import nixpkgs (
|
||||||
|
{
|
||||||
|
system = buildSystem;
|
||||||
|
}
|
||||||
|
// (
|
||||||
|
if targetSystem == null then
|
||||||
|
{ }
|
||||||
|
else
|
||||||
|
{ crossSystem.config = buildTargets.${targetSystem}.crossSystemConfig; }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
in
|
||||||
|
flake-utils.lib.eachDefaultSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
rust = fenix.packages.${system}.stable;
|
||||||
|
in
|
||||||
|
with pkgs;
|
||||||
|
{
|
||||||
|
devShells.default = mkShell {
|
||||||
|
buildInputs = [
|
||||||
|
mosquitto
|
||||||
|
rust.toolchain
|
||||||
|
rust-analyzer
|
||||||
|
sea-orm-cli
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
// {
|
||||||
|
packages = eachCrossSystem (builtins.attrNames buildTargets) (
|
||||||
|
buildSystem: targetSystem:
|
||||||
|
let
|
||||||
|
pkgs = mkPkgs buildSystem null;
|
||||||
|
pkgsCross = mkPkgs buildSystem targetSystem;
|
||||||
|
rustTarget = buildTargets.${targetSystem}.rustTarget;
|
||||||
|
|
||||||
|
fenixPkgs = fenix.packages.${buildSystem};
|
||||||
|
|
||||||
|
mkToolchain = fenixPkgs: fenixPkgs.stable;
|
||||||
|
|
||||||
|
toolchain = fenixPkgs.combine [
|
||||||
|
(mkToolchain fenixPkgs).rustc
|
||||||
|
(mkToolchain fenixPkgs).cargo
|
||||||
|
(mkToolchain fenixPkgs.targets.${rustTarget}).rust-std
|
||||||
|
];
|
||||||
|
|
||||||
|
buildPackageAttrs =
|
||||||
|
if builtins.hasAttr "makeBuildPackageAttrs" buildTargets.${targetSystem} then
|
||||||
|
buildTargets.${targetSystem}.makeBuildPackageAttrs pkgsCross
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
|
||||||
|
naersk-lib = pkgs.callPackage naersk {
|
||||||
|
cargo = toolchain;
|
||||||
|
rustc = toolchain;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
naersk-lib.buildPackage (
|
||||||
|
buildPackageAttrs
|
||||||
|
// rec {
|
||||||
|
src = ./.;
|
||||||
|
strictDeps = true;
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
OPENSSL_STATIC = "1";
|
||||||
|
OPENSSL_LIB_DIR = "${pkgsCross.pkgsStatic.openssl.out}/lib";
|
||||||
|
OPENSSL_INCLUDE_DIR = "${pkgsCross.pkgsStatic.openssl.dev}/include";
|
||||||
|
|
||||||
|
# Required because ring crate is special. This also seems to have
|
||||||
|
# fixed some issues with the x86_64-windows cross-compile :shrug:
|
||||||
|
TARGET_CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc";
|
||||||
|
|
||||||
|
CARGO_BUILD_TARGET = rustTarget;
|
||||||
|
CARGO_BUILD_RUSTFLAGS = [
|
||||||
|
"-C"
|
||||||
|
"target-feature=+crt-static"
|
||||||
|
|
||||||
|
# -latomic is required to build openssl-sys for armv6l-linux, but
|
||||||
|
# it doesn't seem to hurt any other builds.
|
||||||
|
# "-C"
|
||||||
|
# "link-args=-static -latomic"
|
||||||
|
|
||||||
|
"-C"
|
||||||
|
"linker=${TARGET_CC}"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user