Write TableAccessQuerySet for other tables. Create Id macro
This commit is contained in:
1 parent
9a5b64a4fe
commit
d9bbf9e705
8 files changed
+154
-27
No files matched your search
Generated
+6
-2
@@ -2456,6 +2456,7 @@ dependencies = [
|
||||
"hex",
|
||||
"iced",
|
||||
"iced_core",
|
||||
"litemap",
|
||||
"log",
|
||||
"mimalloc",
|
||||
"parking_lot",
|
||||
@@ -2739,9 +2740,12 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
|
||||
checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "litrs"
|
||||
|
||||
@@ -27,6 +27,7 @@ parking_lot = "0.12.5"
|
||||
env_logger = "0.11.11"
|
||||
log = "0.4.34"
|
||||
fsrs = "6.6.1"
|
||||
litemap = { version = "0.8.3", features = ["serde"] }
|
||||
|
||||
[profile.super-release]
|
||||
inherits = "release"
|
||||
|
||||
@@ -19,6 +19,7 @@ use rusqlite::Connection;
|
||||
pub const USER_FONT: Font = Font::with_name("Noto Sans JP");
|
||||
|
||||
pub fn start() -> iced::Result {
|
||||
println!("{}", size_of::<WordData>());
|
||||
info!("Welcome to JapLearn");
|
||||
iced::application(ScreenState::boot, ScreenState::update, ScreenState::view)
|
||||
.window(window_settings())
|
||||
|
||||
+23
-16
@@ -7,57 +7,64 @@ use std::fmt::{write, Display, Formatter};
|
||||
use std::num::ParseIntError;
|
||||
use std::str::FromStr;
|
||||
|
||||
macro_rules! id_impl {
|
||||
($id_type:ty, $name:ident, $invalid:ident) => {
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash, Copy, Ord, PartialOrd, Default)]
|
||||
pub struct Id(pub(crate) u32);
|
||||
pub const INVALID_ID: Id = Id(0);
|
||||
impl FromStr for Id {
|
||||
pub struct $name(pub(crate) $id_type);
|
||||
pub const $invalid: $name = $name(0);
|
||||
impl FromStr for $name {
|
||||
type Err = ParseIntError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Id(s.parse::<u32>()?))
|
||||
Ok($name(s.parse::<$id_type>()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Id {
|
||||
fn from(value: u32) -> Self {
|
||||
Id(value)
|
||||
impl From<$id_type> for $name {
|
||||
fn from(value: $id_type) -> Self {
|
||||
$name(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Id> for u32 {
|
||||
fn from(value: Id) -> Self {
|
||||
impl From<$name> for $id_type {
|
||||
fn from(value: $name) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
impl Display for Id {
|
||||
impl Display for $name {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql for Id {
|
||||
impl FromSql for $name {
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
match value {
|
||||
ValueRef::Integer(i) => Ok(Id(i as u32)),
|
||||
ValueRef::Integer(i) => Ok($name(i as $id_type)),
|
||||
_ => Err(FromSqlError::InvalidType),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql for Id {
|
||||
impl ToSql for $name {
|
||||
fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
|
||||
Ok(ToSqlOutput::from(self.0 as i64))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Id> for String {
|
||||
fn from(value: Id) -> Self {
|
||||
impl From<$name> for String {
|
||||
fn from(value: $name) -> Self {
|
||||
value.0.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Id {
|
||||
impl $name {
|
||||
pub(crate) fn is_valid(self) -> bool {
|
||||
self.0 != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id_impl!(u32, Id, INVALID_ID);
|
||||
id_impl!(u16, SmallId, INVALID_SMALL_ID);
|
||||
+24
-3
@@ -7,18 +7,18 @@ use log::info;
|
||||
use rayon::prelude::*;
|
||||
use rhai::{Engine, Scope};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Instant;
|
||||
use litemap::LiteMap;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WordData {
|
||||
pub id: Id,
|
||||
pub group_id: Id,
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
pub tags: String,
|
||||
pub additional: HashMap<String, String>,
|
||||
pub group_id: Id,
|
||||
pub additional: LiteMap<String, String>,
|
||||
}
|
||||
|
||||
impl EntityData for WordData {
|
||||
@@ -37,6 +37,16 @@ pub struct WordGroup {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl EntityData for WordGroup {
|
||||
fn id(&self) -> Id {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: Id) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl WordData {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@@ -155,6 +165,17 @@ pub struct CardState {
|
||||
pub fsrs_memory: Option<MemoryState>,
|
||||
pub fsrs_open_day: NaiveDate,
|
||||
}
|
||||
|
||||
impl EntityData for CardState {
|
||||
fn id(&self) -> Id {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: Id) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl CardState {
|
||||
pub fn update(&mut self, status: WordOpenMode) {
|
||||
match status {
|
||||
|
||||
@@ -65,8 +65,13 @@ pub fn default_connection() -> Connection {
|
||||
.execute("PRAGMA foreign_keys = ON;", [])
|
||||
.expect("Failed to set PRAGMA");
|
||||
connection
|
||||
.execute("PRAGMA journal_mode = WAL;", [])
|
||||
.expect("Failed to set PRAGMA");
|
||||
.query_one("PRAGMA journal_mode = WAL;", [], |row| {
|
||||
println!("{:?}", row);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap_or_else(|e| {
|
||||
println!("{}", e);
|
||||
});
|
||||
connection
|
||||
.execute("PRAGMA synchronous = NORMAL;", [])
|
||||
.expect("Failed to set PRAGMA");
|
||||
|
||||
@@ -1,8 +1,96 @@
|
||||
use crate::data::entities::{WordData, WordGroup};
|
||||
use crate::data_provider::TableAccessQuerySet;
|
||||
use crate::notification::NotificationData::{DbLoadError, DbSaveError};
|
||||
use crate::notification::{MaybeError, NotificationData};
|
||||
use rusqlite::{Connection, params};
|
||||
use rusqlite::{Connection, Error, Params, Row, params};
|
||||
use std::collections::HashMap;
|
||||
use litemap::LiteMap;
|
||||
|
||||
pub struct WordQuerySet;
|
||||
impl TableAccessQuerySet<WordData> for WordQuerySet {
|
||||
fn load() -> &'static str {
|
||||
"SELECT id, key, value, tags, more, group_id FROM words"
|
||||
}
|
||||
|
||||
fn save() -> &'static str {
|
||||
"UPDATE words SET key = ?1, value = ?2, tags = ?3, more = ?4 WHERE id = ?5"
|
||||
}
|
||||
|
||||
fn add() -> &'static str {
|
||||
"INSERT INTO words (key, value, tags, more, group_id) VALUES (?1, ?2, ?3, ?4, ?5)"
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"words"
|
||||
}
|
||||
|
||||
fn from_sql(row: &Row) -> Result<WordData, Error> {
|
||||
let additional: String = row.get(4)?;
|
||||
Ok(WordData {
|
||||
id: row.get(0)?,
|
||||
key: row.get(1)?,
|
||||
value: row.get(2)?,
|
||||
tags: row.get(3)?,
|
||||
additional: serde_json::from_str(&additional)
|
||||
.unwrap_or_default(),
|
||||
group_id: row.get(5)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn insert_params(entity: &WordData) -> impl Params {
|
||||
(
|
||||
&entity.key,
|
||||
&entity.value,
|
||||
&entity.tags,
|
||||
serde_json::to_string(&entity.additional).unwrap_or_default(),
|
||||
entity.group_id,
|
||||
)
|
||||
}
|
||||
|
||||
fn update_params(entity: &WordData) -> impl Params {
|
||||
(
|
||||
&entity.key,
|
||||
&entity.value,
|
||||
&entity.tags,
|
||||
serde_json::to_string(&entity.additional).unwrap_or_default(),
|
||||
entity.id,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WordGroupQuerySet;
|
||||
impl TableAccessQuerySet<WordGroup> for WordGroupQuerySet {
|
||||
fn load() -> &'static str {
|
||||
"SELECT id, name FROM word_groups"
|
||||
}
|
||||
|
||||
fn save() -> &'static str {
|
||||
"UPDATE word_groups SET name = ?1 WHERE id = ?2"
|
||||
}
|
||||
|
||||
fn add() -> &'static str {
|
||||
"INSERT INTO word_groups (name) VALUES (?1)"
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"word_groups"
|
||||
}
|
||||
|
||||
fn from_sql(row: &Row) -> Result<WordGroup, Error> {
|
||||
Ok(WordGroup {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn insert_params(entity: &WordGroup) -> impl Params {
|
||||
(&entity.name,)
|
||||
}
|
||||
|
||||
fn update_params(entity: &WordGroup) -> impl Params {
|
||||
(&entity.name, entity.id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_word(word: &mut WordData, connection: &Connection) -> MaybeError {
|
||||
let index : u32 = connection
|
||||
@@ -99,7 +187,7 @@ pub fn load_words(connection: &Connection) -> Result<Vec<WordData>, Notification
|
||||
key: row.get(1)?,
|
||||
value: row.get(2)?,
|
||||
tags: row.get(3)?,
|
||||
additional: serde_json::from_str::<HashMap<String, String>>(&additional)
|
||||
additional: serde_json::from_str(&additional)
|
||||
.unwrap_or_default(),
|
||||
group_id: row.get(5)?,
|
||||
})
|
||||
|
||||
+2
-2
@@ -139,7 +139,7 @@ impl NotificationManager {
|
||||
fn draw_data<'a>(data: &NotificationData) -> Element<'a, NotificationMessage> {
|
||||
match data {
|
||||
NotificationData::DataLoaded => {
|
||||
text!("Данные успешно скачаны")
|
||||
text!("Данные успешно загружены на сервер")
|
||||
}
|
||||
NotificationData::ImportError => {
|
||||
text!("Ошибка при импорте данных из Anki")
|
||||
@@ -154,7 +154,7 @@ impl NotificationManager {
|
||||
text!("Не получается подключиться к VoiceVox")
|
||||
}
|
||||
NotificationData::PermissionDenied => {
|
||||
text!("У приложение недостаточно прав")
|
||||
text!("У приложение недостаточно прав для доступа в файлам")
|
||||
}
|
||||
NotificationData::WebApiUnavailable => {
|
||||
text!("Не получается подключиться к Api")
|
||||
|
||||
Reference in new issue
Block a user