use mixed case for abbreviations in Rust code

So, this is fun. Apparently "DeckId" is considered preferable to the
"DeckID" were were using until now, and the latest clippy will start
warning about it. We could of course disable the warning, but probably
better to bite the bullet and switch to the naming that's generally
considered best.
This commit is contained in:
Damien Elmes 2021-03-27 19:53:33 +10:00
parent 89d249b3b6
commit dc81a7fed0
89 changed files with 649 additions and 649 deletions

View File

@ -6,8 +6,8 @@ use std::sync::Arc;
use crate::prelude::*; use crate::prelude::*;
pub struct DeckAndNotetype { pub struct DeckAndNotetype {
pub deck_id: DeckID, pub deck_id: DeckId,
pub notetype_id: NoteTypeID, pub notetype_id: NoteTypeId,
} }
impl Collection { impl Collection {
@ -23,7 +23,7 @@ impl Collection {
/// Default otherwise. /// Default otherwise.
pub fn defaults_for_adding( pub fn defaults_for_adding(
&mut self, &mut self,
home_deck_of_reviewer_card: DeckID, home_deck_of_reviewer_card: DeckId,
) -> Result<DeckAndNotetype> { ) -> Result<DeckAndNotetype> {
let deck_id; let deck_id;
let notetype_id; let notetype_id;
@ -52,7 +52,7 @@ impl Collection {
/// The currently selected deck, the home deck of the provided card, or the default deck. /// The currently selected deck, the home deck of the provided card, or the default deck.
fn get_current_deck_for_adding( fn get_current_deck_for_adding(
&mut self, &mut self,
home_deck_of_reviewer_card: DeckID, home_deck_of_reviewer_card: DeckId,
) -> Result<Arc<Deck>> { ) -> Result<Arc<Deck>> {
// current deck, if not filtered // current deck, if not filtered
if let Some(current) = self.get_deck(self.get_current_deck_id())? { if let Some(current) = self.get_deck(self.get_current_deck_id())? {
@ -65,7 +65,7 @@ impl Collection {
return Ok(home_deck); return Ok(home_deck);
} }
// default deck // default deck
self.get_deck(DeckID(1))?.ok_or(AnkiError::NotFound) self.get_deck(DeckId(1))?.ok_or(AnkiError::NotFound)
} }
fn get_current_notetype_for_adding(&mut self) -> Result<Arc<NoteType>> { fn get_current_notetype_for_adding(&mut self) -> Result<Arc<NoteType>> {
@ -83,7 +83,7 @@ impl Collection {
} }
} }
fn default_notetype_for_deck(&mut self, deck: DeckID) -> Result<Arc<NoteType>> { fn default_notetype_for_deck(&mut self, deck: DeckId) -> Result<Arc<NoteType>> {
// try last notetype used by deck // try last notetype used by deck
if let Some(ntid) = self.get_last_notetype_for_deck(deck) { if let Some(ntid) = self.get_last_notetype_for_deck(deck) {
if let Some(nt) = self.get_notetype(ntid)? { if let Some(nt) = self.get_notetype(ntid)? {
@ -99,7 +99,7 @@ impl Collection {
/// This is optional due to the inconsistent handling, where changes in notetype /// This is optional due to the inconsistent handling, where changes in notetype
/// may need to update the current deck, but not vice versa. If a previous deck is /// may need to update the current deck, but not vice versa. If a previous deck is
/// not set, we want to keep the current selection, instead of resetting it. /// not set, we want to keep the current selection, instead of resetting it.
pub(crate) fn default_deck_for_notetype(&mut self, ntid: NoteTypeID) -> Result<Option<DeckID>> { pub(crate) fn default_deck_for_notetype(&mut self, ntid: NoteTypeId) -> Result<Option<DeckId>> {
if let Some(last_deck_id) = self.get_last_deck_added_to_for_notetype(ntid) { if let Some(last_deck_id) = self.get_last_deck_added_to_for_notetype(ntid) {
if let Some(deck) = self.get_deck(last_deck_id)? { if let Some(deck) = self.get_deck(last_deck_id)? {
if !deck.is_filtered() { if !deck.is_filtered() {

View File

@ -45,7 +45,7 @@ impl CardsService for Backend {
} }
fn set_deck(&self, input: pb::SetDeckIn) -> Result<pb::OpChanges> { fn set_deck(&self, input: pb::SetDeckIn) -> Result<pb::OpChanges> {
let cids: Vec<_> = input.card_ids.into_iter().map(CardID).collect(); let cids: Vec<_> = input.card_ids.into_iter().map(CardId).collect();
let deck_id = input.deck_id.into(); let deck_id = input.deck_id.into();
self.with_col(|col| col.set_deck(&cids, deck_id).map(Into::into)) self.with_col(|col| col.set_deck(&cids, deck_id).map(Into::into))
} }
@ -67,9 +67,9 @@ impl TryFrom<pb::Card> for Card {
let queue = CardQueue::try_from(c.queue as i8) let queue = CardQueue::try_from(c.queue as i8)
.map_err(|_| AnkiError::invalid_input("invalid card queue"))?; .map_err(|_| AnkiError::invalid_input("invalid card queue"))?;
Ok(Card { Ok(Card {
id: CardID(c.id), id: CardId(c.id),
note_id: NoteID(c.note_id), note_id: NoteId(c.note_id),
deck_id: DeckID(c.deck_id), deck_id: DeckId(c.deck_id),
template_idx: c.template_idx as u16, template_idx: c.template_idx as u16,
mtime: TimestampSecs(c.mtime_secs), mtime: TimestampSecs(c.mtime_secs),
usn: Usn(c.usn), usn: Usn(c.usn),
@ -82,7 +82,7 @@ impl TryFrom<pb::Card> for Card {
lapses: c.lapses, lapses: c.lapses,
remaining_steps: c.remaining_steps, remaining_steps: c.remaining_steps,
original_due: c.original_due, original_due: c.original_due,
original_deck_id: DeckID(c.original_deck_id), original_deck_id: DeckId(c.original_deck_id),
flags: c.flags as u8, flags: c.flags as u8,
data: c.data, data: c.data,
}) })
@ -114,6 +114,6 @@ impl From<Card> for pb::Card {
} }
} }
fn to_card_ids(v: Vec<i64>) -> Vec<CardID> { fn to_card_ids(v: Vec<i64>) -> Vec<CardId> {
v.into_iter().map(CardID).collect() v.into_iter().map(CardId).collect()
} }

View File

@ -9,7 +9,7 @@ use crate::{
notetype::{CardTemplateSchema11, RenderCardOutput}, notetype::{CardTemplateSchema11, RenderCardOutput},
prelude::*, prelude::*,
template::RenderedNode, template::RenderedNode,
text::{extract_av_tags, sanitize_html_no_images, strip_av_tags, AVTag}, text::{extract_av_tags, sanitize_html_no_images, strip_av_tags, AvTag},
}; };
pub(super) use pb::cardrendering_service::Service as CardRenderingService; pub(super) use pb::cardrendering_service::Service as CardRenderingService;
@ -19,10 +19,10 @@ impl CardRenderingService for Backend {
let pt_tags = tags let pt_tags = tags
.into_iter() .into_iter()
.map(|avtag| match avtag { .map(|avtag| match avtag {
AVTag::SoundOrVideo(file) => pb::AvTag { AvTag::SoundOrVideo(file) => pb::AvTag {
value: Some(pb::av_tag::Value::SoundOrVideo(file)), value: Some(pb::av_tag::Value::SoundOrVideo(file)),
}, },
AVTag::TextToSpeech { AvTag::TextToSpeech {
field_text, field_text,
lang, lang,
voices, voices,
@ -90,7 +90,7 @@ impl CardRenderingService for Backend {
fn render_existing_card(&self, input: pb::RenderExistingCardIn) -> Result<pb::RenderCardOut> { fn render_existing_card(&self, input: pb::RenderExistingCardIn) -> Result<pb::RenderCardOut> {
self.with_col(|col| { self.with_col(|col| {
col.render_existing_card(CardID(input.card_id), input.browser) col.render_existing_card(CardId(input.card_id), input.browser)
.map(Into::into) .map(Into::into)
}) })
} }

View File

@ -9,7 +9,7 @@ use serde_derive::{Deserialize, Serialize};
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(tag = "kind", rename_all = "lowercase")] #[serde(tag = "kind", rename_all = "lowercase")]
pub(super) enum DBRequest { pub(super) enum DbRequest {
Query { Query {
sql: String, sql: String,
args: Vec<SqlValue>, args: Vec<SqlValue>,
@ -26,7 +26,7 @@ pub(super) enum DBRequest {
#[derive(Serialize)] #[derive(Serialize)]
#[serde(untagged)] #[serde(untagged)]
pub(super) enum DBResult { pub(super) enum DbResult {
Rows(Vec<Vec<SqlValue>>), Rows(Vec<Vec<SqlValue>>),
None, None,
} }
@ -68,9 +68,9 @@ impl FromSql for SqlValue {
} }
pub(super) fn db_command_bytes(col: &mut Collection, input: &[u8]) -> Result<Vec<u8>> { pub(super) fn db_command_bytes(col: &mut Collection, input: &[u8]) -> Result<Vec<u8>> {
let req: DBRequest = serde_json::from_slice(input)?; let req: DbRequest = serde_json::from_slice(input)?;
let resp = match req { let resp = match req {
DBRequest::Query { DbRequest::Query {
sql, sql,
args, args,
first_row_only, first_row_only,
@ -82,24 +82,24 @@ pub(super) fn db_command_bytes(col: &mut Collection, input: &[u8]) -> Result<Vec
db_query(&col.storage, &sql, &args)? db_query(&col.storage, &sql, &args)?
} }
} }
DBRequest::Begin => { DbRequest::Begin => {
col.storage.begin_trx()?; col.storage.begin_trx()?;
DBResult::None DbResult::None
} }
DBRequest::Commit => { DbRequest::Commit => {
if col.state.modified_by_dbproxy { if col.state.modified_by_dbproxy {
col.storage.set_modified()?; col.storage.set_modified()?;
col.state.modified_by_dbproxy = false; col.state.modified_by_dbproxy = false;
} }
col.storage.commit_trx()?; col.storage.commit_trx()?;
DBResult::None DbResult::None
} }
DBRequest::Rollback => { DbRequest::Rollback => {
col.clear_caches(); col.clear_caches();
col.storage.rollback_trx()?; col.storage.rollback_trx()?;
DBResult::None DbResult::None
} }
DBRequest::ExecuteMany { sql, args } => { DbRequest::ExecuteMany { sql, args } => {
update_state_after_modification(col, &sql); update_state_after_modification(col, &sql);
db_execute_many(&col.storage, &sql, &args)? db_execute_many(&col.storage, &sql, &args)?
} }
@ -125,7 +125,7 @@ fn is_dql(sql: &str) -> bool {
head.starts_with("select ") head.starts_with("select ")
} }
pub(super) fn db_query_row(ctx: &SqliteStorage, sql: &str, args: &[SqlValue]) -> Result<DBResult> { pub(super) fn db_query_row(ctx: &SqliteStorage, sql: &str, args: &[SqlValue]) -> Result<DbResult> {
let mut stmt = ctx.db.prepare_cached(sql)?; let mut stmt = ctx.db.prepare_cached(sql)?;
let columns = stmt.column_count(); let columns = stmt.column_count();
@ -146,10 +146,10 @@ pub(super) fn db_query_row(ctx: &SqliteStorage, sql: &str, args: &[SqlValue]) ->
vec![] vec![]
}; };
Ok(DBResult::Rows(rows)) Ok(DbResult::Rows(rows))
} }
pub(super) fn db_query(ctx: &SqliteStorage, sql: &str, args: &[SqlValue]) -> Result<DBResult> { pub(super) fn db_query(ctx: &SqliteStorage, sql: &str, args: &[SqlValue]) -> Result<DbResult> {
let mut stmt = ctx.db.prepare_cached(sql)?; let mut stmt = ctx.db.prepare_cached(sql)?;
let columns = stmt.column_count(); let columns = stmt.column_count();
@ -164,19 +164,19 @@ pub(super) fn db_query(ctx: &SqliteStorage, sql: &str, args: &[SqlValue]) -> Res
})? })?
.collect(); .collect();
Ok(DBResult::Rows(res?)) Ok(DbResult::Rows(res?))
} }
pub(super) fn db_execute_many( pub(super) fn db_execute_many(
ctx: &SqliteStorage, ctx: &SqliteStorage,
sql: &str, sql: &str,
args: &[Vec<SqlValue>], args: &[Vec<SqlValue>],
) -> Result<DBResult> { ) -> Result<DbResult> {
let mut stmt = ctx.db.prepare_cached(sql)?; let mut stmt = ctx.db.prepare_cached(sql)?;
for params in args { for params in args {
stmt.execute(params)?; stmt.execute(params)?;
} }
Ok(DBResult::None) Ok(DbResult::None)
} }

View File

@ -4,7 +4,7 @@
use super::Backend; use super::Backend;
use crate::{ use crate::{
backend_proto::{self as pb}, backend_proto::{self as pb},
decks::{Deck, DeckID, DeckSchema11}, decks::{Deck, DeckId, DeckSchema11},
prelude::*, prelude::*,
scheduler::filtered::FilteredDeckForUpdate, scheduler::filtered::FilteredDeckForUpdate,
}; };
@ -38,7 +38,7 @@ impl DecksService for Backend {
fn deck_tree(&self, input: pb::DeckTreeIn) -> Result<pb::DeckTreeNode> { fn deck_tree(&self, input: pb::DeckTreeIn) -> Result<pb::DeckTreeNode> {
let lim = if input.top_deck_id > 0 { let lim = if input.top_deck_id > 0 {
Some(DeckID(input.top_deck_id)) Some(DeckId(input.top_deck_id))
} else { } else {
None None
}; };
@ -120,7 +120,7 @@ impl DecksService for Backend {
} }
fn remove_decks(&self, input: pb::DeckIDs) -> Result<pb::OpChangesWithCount> { fn remove_decks(&self, input: pb::DeckIDs) -> Result<pb::OpChangesWithCount> {
self.with_col(|col| col.remove_decks_and_child_decks(&Into::<Vec<DeckID>>::into(input))) self.with_col(|col| col.remove_decks_and_child_decks(&Into::<Vec<DeckId>>::into(input)))
.map(Into::into) .map(Into::into)
} }
@ -155,20 +155,20 @@ impl DecksService for Backend {
} }
} }
impl From<pb::DeckId> for DeckID { impl From<pb::DeckId> for DeckId {
fn from(did: pb::DeckId) -> Self { fn from(did: pb::DeckId) -> Self {
DeckID(did.did) DeckId(did.did)
} }
} }
impl From<pb::DeckIDs> for Vec<DeckID> { impl From<pb::DeckIDs> for Vec<DeckId> {
fn from(dids: pb::DeckIDs) -> Self { fn from(dids: pb::DeckIDs) -> Self {
dids.dids.into_iter().map(DeckID).collect() dids.dids.into_iter().map(DeckId).collect()
} }
} }
impl From<DeckID> for pb::DeckId { impl From<DeckId> for pb::DeckId {
fn from(did: DeckID) -> Self { fn from(did: DeckId) -> Self {
pb::DeckId { did: did.0 } pb::DeckId { did: did.0 }
} }
} }

View File

@ -14,8 +14,8 @@ pub(super) fn anki_error_to_proto_error(err: AnkiError, tr: &I18n) -> pb::Backen
let value = match err { let value = match err {
AnkiError::InvalidInput { .. } => V::InvalidInput(pb::Empty {}), AnkiError::InvalidInput { .. } => V::InvalidInput(pb::Empty {}),
AnkiError::TemplateError { .. } => V::TemplateParse(pb::Empty {}), AnkiError::TemplateError { .. } => V::TemplateParse(pb::Empty {}),
AnkiError::IOError { .. } => V::IoError(pb::Empty {}), AnkiError::IoError { .. } => V::IoError(pb::Empty {}),
AnkiError::DBError { .. } => V::DbError(pb::Empty {}), AnkiError::DbError { .. } => V::DbError(pb::Empty {}),
AnkiError::NetworkError { kind, .. } => { AnkiError::NetworkError { kind, .. } => {
V::NetworkError(pb::NetworkError { kind: kind.into() }) V::NetworkError(pb::NetworkError { kind: kind.into() })
} }
@ -23,7 +23,7 @@ pub(super) fn anki_error_to_proto_error(err: AnkiError, tr: &I18n) -> pb::Backen
AnkiError::Interrupted => V::Interrupted(pb::Empty {}), AnkiError::Interrupted => V::Interrupted(pb::Empty {}),
AnkiError::CollectionNotOpen => V::InvalidInput(pb::Empty {}), AnkiError::CollectionNotOpen => V::InvalidInput(pb::Empty {}),
AnkiError::CollectionAlreadyOpen => V::InvalidInput(pb::Empty {}), AnkiError::CollectionAlreadyOpen => V::InvalidInput(pb::Empty {}),
AnkiError::JSONError { info } => V::JsonError(info), AnkiError::JsonError { info } => V::JsonError(info),
AnkiError::ProtoError { info } => V::ProtoError(info), AnkiError::ProtoError { info } => V::ProtoError(info),
AnkiError::NotFound => V::NotFoundError(pb::Empty {}), AnkiError::NotFound => V::NotFoundError(pb::Empty {}),
AnkiError::Existing => V::Exists(pb::Empty {}), AnkiError::Existing => V::Exists(pb::Empty {}),

View File

@ -45,33 +45,33 @@ impl From<()> for pb::Empty {
} }
} }
impl From<pb::CardId> for CardID { impl From<pb::CardId> for CardId {
fn from(cid: pb::CardId) -> Self { fn from(cid: pb::CardId) -> Self {
CardID(cid.cid) CardId(cid.cid)
} }
} }
impl Into<Vec<CardID>> for pb::CardIDs { impl Into<Vec<CardId>> for pb::CardIDs {
fn into(self) -> Vec<CardID> { fn into(self) -> Vec<CardId> {
self.cids.into_iter().map(CardID).collect() self.cids.into_iter().map(CardId).collect()
} }
} }
impl From<pb::NoteId> for NoteID { impl From<pb::NoteId> for NoteId {
fn from(nid: pb::NoteId) -> Self { fn from(nid: pb::NoteId) -> Self {
NoteID(nid.nid) NoteId(nid.nid)
} }
} }
impl From<pb::NoteTypeId> for NoteTypeID { impl From<pb::NoteTypeId> for NoteTypeId {
fn from(ntid: pb::NoteTypeId) -> Self { fn from(ntid: pb::NoteTypeId) -> Self {
NoteTypeID(ntid.ntid) NoteTypeId(ntid.ntid)
} }
} }
impl From<pb::DeckConfigId> for DeckConfID { impl From<pb::DeckConfigId> for DeckConfId {
fn from(dcid: pb::DeckConfigId) -> Self { fn from(dcid: pb::DeckConfigId) -> Self {
DeckConfID(dcid.dcid) DeckConfId(dcid.dcid)
} }
} }

View File

@ -22,7 +22,7 @@ impl NotesService for Backend {
fn add_note(&self, input: pb::AddNoteIn) -> Result<pb::AddNoteOut> { fn add_note(&self, input: pb::AddNoteIn) -> Result<pb::AddNoteOut> {
self.with_col(|col| { self.with_col(|col| {
let mut note: Note = input.note.ok_or(AnkiError::NotFound)?.into(); let mut note: Note = input.note.ok_or(AnkiError::NotFound)?.into();
let changes = col.add_note(&mut note, DeckID(input.deck_id))?; let changes = col.add_note(&mut note, DeckId(input.deck_id))?;
Ok(pb::AddNoteOut { Ok(pb::AddNoteOut {
note_id: note.id.0, note_id: note.id.0,
changes: Some(changes.into()), changes: Some(changes.into()),
@ -32,7 +32,7 @@ impl NotesService for Backend {
fn defaults_for_adding(&self, input: pb::DefaultsForAddingIn) -> Result<pb::DeckAndNotetype> { fn defaults_for_adding(&self, input: pb::DefaultsForAddingIn) -> Result<pb::DeckAndNotetype> {
self.with_col(|col| { self.with_col(|col| {
let home_deck: DeckID = input.home_deck_of_current_review_card.into(); let home_deck: DeckId = input.home_deck_of_current_review_card.into();
col.defaults_for_adding(home_deck).map(Into::into) col.defaults_for_adding(home_deck).map(Into::into)
}) })
} }
@ -41,7 +41,7 @@ impl NotesService for Backend {
self.with_col(|col| { self.with_col(|col| {
Ok(col Ok(col
.default_deck_for_notetype(input.into())? .default_deck_for_notetype(input.into())?
.unwrap_or(DeckID(0)) .unwrap_or(DeckId(0))
.into()) .into())
}) })
} }
@ -113,7 +113,7 @@ impl NotesService for Backend {
input: pb::FieldNamesForNotesIn, input: pb::FieldNamesForNotesIn,
) -> Result<pb::FieldNamesForNotesOut> { ) -> Result<pb::FieldNamesForNotesOut> {
self.with_col(|col| { self.with_col(|col| {
let nids: Vec<_> = input.nids.into_iter().map(NoteID).collect(); let nids: Vec<_> = input.nids.into_iter().map(NoteId).collect();
col.storage col.storage
.field_names_for_notes(&nids) .field_names_for_notes(&nids)
.map(|fields| pb::FieldNamesForNotesOut { fields }) .map(|fields| pb::FieldNamesForNotesOut { fields })
@ -131,7 +131,7 @@ impl NotesService for Backend {
fn cards_of_note(&self, input: pb::NoteId) -> Result<pb::CardIDs> { fn cards_of_note(&self, input: pb::NoteId) -> Result<pb::CardIDs> {
self.with_col(|col| { self.with_col(|col| {
col.storage col.storage
.all_card_ids_of_note(NoteID(input.nid)) .all_card_ids_of_note(NoteId(input.nid))
.map(|v| pb::CardIDs { .map(|v| pb::CardIDs {
cids: v.into_iter().map(Into::into).collect(), cids: v.into_iter().map(Into::into).collect(),
}) })
@ -139,6 +139,6 @@ impl NotesService for Backend {
} }
} }
pub(super) fn to_note_ids(ids: Vec<i64>) -> Vec<NoteID> { pub(super) fn to_note_ids(ids: Vec<i64>) -> Vec<NoteId> {
ids.into_iter().map(NoteID).collect() ids.into_iter().map(NoteId).collect()
} }

View File

@ -13,7 +13,7 @@ use crate::{
impl From<pb::AnswerCardIn> for CardAnswer { impl From<pb::AnswerCardIn> for CardAnswer {
fn from(answer: pb::AnswerCardIn) -> Self { fn from(answer: pb::AnswerCardIn) -> Self {
CardAnswer { CardAnswer {
card_id: CardID(answer.card_id), card_id: CardId(answer.card_id),
rating: answer.rating().into(), rating: answer.rating().into(),
current_state: answer.current_state.unwrap_or_default().into(), current_state: answer.current_state.unwrap_or_default().into(),
new_state: answer.new_state.unwrap_or_default().into(), new_state: answer.new_state.unwrap_or_default().into(),

View File

@ -90,7 +90,7 @@ impl SchedulingService for Backend {
fn bury_or_suspend_cards(&self, input: pb::BuryOrSuspendCardsIn) -> Result<pb::OpChanges> { fn bury_or_suspend_cards(&self, input: pb::BuryOrSuspendCardsIn) -> Result<pb::OpChanges> {
self.with_col(|col| { self.with_col(|col| {
let mode = input.mode(); let mode = input.mode();
let cids: Vec<_> = input.card_ids.into_iter().map(CardID).collect(); let cids: Vec<_> = input.card_ids.into_iter().map(CardId).collect();
col.bury_or_suspend_cards(&cids, mode).map(Into::into) col.bury_or_suspend_cards(&cids, mode).map(Into::into)
}) })
} }
@ -105,7 +105,7 @@ impl SchedulingService for Backend {
fn schedule_cards_as_new(&self, input: pb::ScheduleCardsAsNewIn) -> Result<pb::OpChanges> { fn schedule_cards_as_new(&self, input: pb::ScheduleCardsAsNewIn) -> Result<pb::OpChanges> {
self.with_col(|col| { self.with_col(|col| {
let cids: Vec<_> = input.card_ids.into_iter().map(CardID).collect(); let cids: Vec<_> = input.card_ids.into_iter().map(CardId).collect();
let log = input.log; let log = input.log;
col.reschedule_cards_as_new(&cids, log).map(Into::into) col.reschedule_cards_as_new(&cids, log).map(Into::into)
}) })
@ -114,12 +114,12 @@ impl SchedulingService for Backend {
fn set_due_date(&self, input: pb::SetDueDateIn) -> Result<pb::OpChanges> { fn set_due_date(&self, input: pb::SetDueDateIn) -> Result<pb::OpChanges> {
let config = input.config_key.map(Into::into); let config = input.config_key.map(Into::into);
let days = input.days; let days = input.days;
let cids: Vec<_> = input.card_ids.into_iter().map(CardID).collect(); let cids: Vec<_> = input.card_ids.into_iter().map(CardId).collect();
self.with_col(|col| col.set_due_date(&cids, &days, config).map(Into::into)) self.with_col(|col| col.set_due_date(&cids, &days, config).map(Into::into))
} }
fn sort_cards(&self, input: pb::SortCardsIn) -> Result<pb::OpChangesWithCount> { fn sort_cards(&self, input: pb::SortCardsIn) -> Result<pb::OpChangesWithCount> {
let cids: Vec<_> = input.card_ids.into_iter().map(CardID).collect(); let cids: Vec<_> = input.card_ids.into_iter().map(CardId).collect();
let (start, step, random, shift) = ( let (start, step, random, shift) = (
input.starting_from, input.starting_from,
input.step_size, input.step_size,
@ -145,7 +145,7 @@ impl SchedulingService for Backend {
} }
fn get_next_card_states(&self, input: pb::CardId) -> Result<pb::NextCardStates> { fn get_next_card_states(&self, input: pb::CardId) -> Result<pb::NextCardStates> {
let cid: CardID = input.into(); let cid: CardId = input.into();
self.with_col(|col| col.get_next_card_states(cid)) self.with_col(|col| col.get_next_card_states(cid))
.map(Into::into) .map(Into::into)
} }

View File

@ -75,7 +75,7 @@ impl SearchService for Backend {
if !input.match_case { if !input.match_case {
search = format!("(?i){}", search); search = format!("(?i){}", search);
} }
let nids = input.nids.into_iter().map(NoteID).collect(); let nids = input.nids.into_iter().map(NoteId).collect();
let field_name = if input.field_name.is_empty() { let field_name = if input.field_name.is_empty() {
None None
} else { } else {

View File

@ -33,8 +33,8 @@ impl TryFrom<pb::SearchNode> for Node {
Filter::Template(u) => { Filter::Template(u) => {
Node::Search(SearchNode::CardTemplate(TemplateKind::Ordinal(u as u16))) Node::Search(SearchNode::CardTemplate(TemplateKind::Ordinal(u as u16)))
} }
Filter::Nid(nid) => Node::Search(SearchNode::NoteIDs(nid.to_string())), Filter::Nid(nid) => Node::Search(SearchNode::NoteIds(nid.to_string())),
Filter::Nids(nids) => Node::Search(SearchNode::NoteIDs(nids.into_id_string())), Filter::Nids(nids) => Node::Search(SearchNode::NoteIds(nids.into_id_string())),
Filter::Dupe(dupe) => Node::Search(SearchNode::Duplicates { Filter::Dupe(dupe) => Node::Search(SearchNode::Duplicates {
note_type_id: dupe.notetype_id.into(), note_type_id: dupe.notetype_id.into(),
text: dupe.first_field, text: dupe.first_field,

View File

@ -8,9 +8,9 @@ use itertools::Itertools;
use crate::err::{AnkiError, Result}; use crate::err::{AnkiError, Result};
use crate::i18n::I18n; use crate::i18n::I18n;
use crate::{ use crate::{
card::{Card, CardID, CardQueue, CardType}, card::{Card, CardId, CardQueue, CardType},
collection::Collection, collection::Collection,
decks::{Deck, DeckID}, decks::{Deck, DeckId},
notes::Note, notes::Note,
notetype::{CardTemplate, NoteType, NoteTypeKind}, notetype::{CardTemplate, NoteType, NoteTypeKind},
scheduler::{timespan::time_span, timing::SchedTimingToday}, scheduler::{timespan::time_span, timing::SchedTimingToday},
@ -77,7 +77,7 @@ fn card_render_required(columns: &[String]) -> bool {
} }
impl Collection { impl Collection {
pub fn browser_row_for_card(&mut self, id: CardID) -> Result<Row> { pub fn browser_row_for_card(&mut self, id: CardId) -> Result<Row> {
// this is inefficient; we may want to use an enum in the future // this is inefficient; we may want to use an enum in the future
let columns = self.get_desktop_browser_card_columns(); let columns = self.get_desktop_browser_card_columns();
let mut context = RowContext::new(self, id, card_render_required(&columns))?; let mut context = RowContext::new(self, id, card_render_required(&columns))?;
@ -124,7 +124,7 @@ impl RenderContext {
} }
impl<'a> RowContext<'a> { impl<'a> RowContext<'a> {
fn new(col: &'a mut Collection, id: CardID, with_card_render: bool) -> Result<Self> { fn new(col: &'a mut Collection, id: CardId, with_card_render: bool) -> Result<Self> {
let card = col.storage.get_card(id)?.ok_or(AnkiError::NotFound)?; let card = col.storage.get_card(id)?.ok_or(AnkiError::NotFound)?;
// todo: After note.sort_field has been modified so it can be displayed in the browser, // todo: After note.sort_field has been modified so it can be displayed in the browser,
// we can update note_field_str() and only load the note with fields if a card render is // we can update note_field_str() and only load the note with fields if a card render is
@ -235,7 +235,7 @@ impl<'a> RowContext<'a> {
} }
fn card_due_str(&mut self) -> String { fn card_due_str(&mut self) -> String {
let due = if self.card.original_deck_id != DeckID(0) { let due = if self.card.original_deck_id != DeckId(0) {
self.tr.browsing_filtered() self.tr.browsing_filtered()
} else if self.card.queue == CardQueue::New || self.card.ctype == CardType::New { } else if self.card.queue == CardQueue::New || self.card.ctype == CardType::New {
self.tr.statistics_due_for_new_card(self.card.due) self.tr.statistics_due_for_new_card(self.card.due)

View File

@ -4,21 +4,21 @@
pub(crate) mod undo; pub(crate) mod undo;
use crate::err::{AnkiError, Result}; use crate::err::{AnkiError, Result};
use crate::notes::NoteID; use crate::notes::NoteId;
use crate::{ use crate::{
collection::Collection, config::SchedulerVersion, prelude::*, timestamp::TimestampSecs, collection::Collection, config::SchedulerVersion, prelude::*, timestamp::TimestampSecs,
types::Usn, types::Usn,
}; };
use crate::{define_newtype, ops::StateChanges}; use crate::{define_newtype, ops::StateChanges};
use crate::{deckconf::DeckConf, decks::DeckID}; use crate::{deckconf::DeckConf, decks::DeckId};
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
use serde_repr::{Deserialize_repr, Serialize_repr}; use serde_repr::{Deserialize_repr, Serialize_repr};
use std::collections::HashSet; use std::collections::HashSet;
define_newtype!(CardID, i64); define_newtype!(CardId, i64);
impl CardID { impl CardId {
pub fn as_secs(self) -> TimestampSecs { pub fn as_secs(self) -> TimestampSecs {
TimestampSecs(self.0 / 1000) TimestampSecs(self.0 / 1000)
} }
@ -54,9 +54,9 @@ pub enum CardQueue {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Card { pub struct Card {
pub(crate) id: CardID, pub(crate) id: CardId,
pub(crate) note_id: NoteID, pub(crate) note_id: NoteId,
pub(crate) deck_id: DeckID, pub(crate) deck_id: DeckId,
pub(crate) template_idx: u16, pub(crate) template_idx: u16,
pub(crate) mtime: TimestampSecs, pub(crate) mtime: TimestampSecs,
pub(crate) usn: Usn, pub(crate) usn: Usn,
@ -69,7 +69,7 @@ pub struct Card {
pub(crate) lapses: u32, pub(crate) lapses: u32,
pub(crate) remaining_steps: u32, pub(crate) remaining_steps: u32,
pub(crate) original_due: i32, pub(crate) original_due: i32,
pub(crate) original_deck_id: DeckID, pub(crate) original_deck_id: DeckId,
pub(crate) flags: u8, pub(crate) flags: u8,
pub(crate) data: String, pub(crate) data: String,
} }
@ -77,9 +77,9 @@ pub struct Card {
impl Default for Card { impl Default for Card {
fn default() -> Self { fn default() -> Self {
Self { Self {
id: CardID(0), id: CardId(0),
note_id: NoteID(0), note_id: NoteId(0),
deck_id: DeckID(0), deck_id: DeckId(0),
template_idx: 0, template_idx: 0,
mtime: TimestampSecs(0), mtime: TimestampSecs(0),
usn: Usn(0), usn: Usn(0),
@ -92,7 +92,7 @@ impl Default for Card {
lapses: 0, lapses: 0,
remaining_steps: 0, remaining_steps: 0,
original_due: 0, original_due: 0,
original_deck_id: DeckID(0), original_deck_id: DeckId(0),
flags: 0, flags: 0,
data: "".to_string(), data: "".to_string(),
} }
@ -106,7 +106,7 @@ impl Card {
} }
/// Caller must ensure provided deck exists and is not filtered. /// Caller must ensure provided deck exists and is not filtered.
fn set_deck(&mut self, deck: DeckID, sched: SchedulerVersion) { fn set_deck(&mut self, deck: DeckId, sched: SchedulerVersion) {
self.remove_from_filtered_deck_restoring_queue(sched); self.remove_from_filtered_deck_restoring_queue(sched);
self.deck_id = deck; self.deck_id = deck;
} }
@ -137,7 +137,7 @@ impl Card {
} }
impl Card { impl Card {
pub fn new(note_id: NoteID, template_idx: u16, deck_id: DeckID, due: i32) -> Self { pub fn new(note_id: NoteId, template_idx: u16, deck_id: DeckId, due: i32) -> Self {
Card { Card {
note_id, note_id,
template_idx, template_idx,
@ -177,7 +177,7 @@ impl Collection {
} }
#[cfg(test)] #[cfg(test)]
pub(crate) fn get_and_update_card<F, T>(&mut self, cid: CardID, func: F) -> Result<Card> pub(crate) fn get_and_update_card<F, T>(&mut self, cid: CardId, func: F) -> Result<Card>
where where
F: FnOnce(&mut Card) -> Result<T>, F: FnOnce(&mut Card) -> Result<T>,
{ {
@ -213,7 +213,7 @@ impl Collection {
/// Remove cards and any resulting orphaned notes. /// Remove cards and any resulting orphaned notes.
/// Expects a transaction. /// Expects a transaction.
pub(crate) fn remove_cards_and_orphaned_notes(&mut self, cids: &[CardID]) -> Result<()> { pub(crate) fn remove_cards_and_orphaned_notes(&mut self, cids: &[CardId]) -> Result<()> {
let usn = self.usn()?; let usn = self.usn()?;
let mut nids = HashSet::new(); let mut nids = HashSet::new();
for cid in cids { for cid in cids {
@ -231,7 +231,7 @@ impl Collection {
Ok(()) Ok(())
} }
pub fn set_deck(&mut self, cards: &[CardID], deck_id: DeckID) -> Result<OpOutput<()>> { pub fn set_deck(&mut self, cards: &[CardId], deck_id: DeckId) -> Result<OpOutput<()>> {
let deck = self.get_deck(deck_id)?.ok_or(AnkiError::NotFound)?; let deck = self.get_deck(deck_id)?.ok_or(AnkiError::NotFound)?;
if deck.is_filtered() { if deck.is_filtered() {
return Err(AnkiError::DeckIsFiltered); return Err(AnkiError::DeckIsFiltered);
@ -252,7 +252,7 @@ impl Collection {
}) })
} }
pub fn set_card_flag(&mut self, cards: &[CardID], flag: u32) -> Result<OpOutput<()>> { pub fn set_card_flag(&mut self, cards: &[CardId], flag: u32) -> Result<OpOutput<()>> {
if flag > 4 { if flag > 4 {
return Err(AnkiError::invalid_input("invalid flag")); return Err(AnkiError::invalid_input("invalid flag"));
} }

View File

@ -8,8 +8,8 @@ pub(crate) enum UndoableCardChange {
Added(Box<Card>), Added(Box<Card>),
Updated(Box<Card>), Updated(Box<Card>),
Removed(Box<Card>), Removed(Box<Card>),
GraveAdded(Box<(CardID, Usn)>), GraveAdded(Box<(CardId, Usn)>),
GraveRemoved(Box<(CardID, Usn)>), GraveRemoved(Box<(CardId, Usn)>),
} }
impl Collection { impl Collection {
@ -66,12 +66,12 @@ impl Collection {
Ok(()) Ok(())
} }
fn add_card_grave_undoable(&mut self, cid: CardID, usn: Usn) -> Result<()> { fn add_card_grave_undoable(&mut self, cid: CardId, usn: Usn) -> Result<()> {
self.save_undo(UndoableCardChange::GraveAdded(Box::new((cid, usn)))); self.save_undo(UndoableCardChange::GraveAdded(Box::new((cid, usn))));
self.storage.add_card_grave(cid, usn) self.storage.add_card_grave(cid, usn)
} }
fn remove_card_grave(&mut self, cid: CardID, usn: Usn) -> Result<()> { fn remove_card_grave(&mut self, cid: CardId, usn: Usn) -> Result<()> {
self.save_undo(UndoableCardChange::GraveRemoved(Box::new((cid, usn)))); self.save_undo(UndoableCardChange::GraveRemoved(Box::new((cid, usn))));
self.storage.remove_card_grave(cid) self.storage.remove_card_grave(cid)
} }

View File

@ -4,8 +4,8 @@
use crate::log::Logger; use crate::log::Logger;
use crate::types::Usn; use crate::types::Usn;
use crate::{ use crate::{
decks::{Deck, DeckID}, decks::{Deck, DeckId},
notetype::{NoteType, NoteTypeID}, notetype::{NoteType, NoteTypeId},
prelude::*, prelude::*,
storage::SqliteStorage, storage::SqliteStorage,
undo::UndoManager, undo::UndoManager,
@ -62,8 +62,8 @@ pub fn open_test_collection_with_server(server: bool) -> Collection {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct CollectionState { pub struct CollectionState {
pub(crate) undo: UndoManager, pub(crate) undo: UndoManager,
pub(crate) notetype_cache: HashMap<NoteTypeID, Arc<NoteType>>, pub(crate) notetype_cache: HashMap<NoteTypeId, Arc<NoteType>>,
pub(crate) deck_cache: HashMap<DeckID, Arc<Deck>>, pub(crate) deck_cache: HashMap<DeckId, Arc<Deck>>,
pub(crate) card_queues: Option<CardQueues>, pub(crate) card_queues: Option<CardQueues>,
/// True if legacy Python code has executed SQL that has modified the /// True if legacy Python code has executed SQL that has modified the
/// database, requiring modification time to be bumped. /// database, requiring modification time to be bumped.

View File

@ -14,36 +14,36 @@ enum DeckConfigKey {
} }
impl DeckConfigKey { impl DeckConfigKey {
fn for_deck(self, did: DeckID) -> String { fn for_deck(self, did: DeckId) -> String {
build_aux_deck_key(did, <&'static str>::from(self)) build_aux_deck_key(did, <&'static str>::from(self))
} }
} }
impl Collection { impl Collection {
pub(crate) fn get_current_deck_id(&self) -> DeckID { pub(crate) fn get_current_deck_id(&self) -> DeckId {
self.get_config_optional(ConfigKey::CurrentDeckID) self.get_config_optional(ConfigKey::CurrentDeckId)
.unwrap_or(DeckID(1)) .unwrap_or(DeckId(1))
} }
pub(crate) fn clear_aux_config_for_deck(&self, ntid: DeckID) -> Result<()> { pub(crate) fn clear_aux_config_for_deck(&self, ntid: DeckId) -> Result<()> {
self.remove_config_prefix(&build_aux_deck_key(ntid, "")) self.remove_config_prefix(&build_aux_deck_key(ntid, ""))
} }
pub(crate) fn get_last_notetype_for_deck(&self, id: DeckID) -> Option<NoteTypeID> { pub(crate) fn get_last_notetype_for_deck(&self, id: DeckId) -> Option<NoteTypeId> {
let key = DeckConfigKey::LastNotetype.for_deck(id); let key = DeckConfigKey::LastNotetype.for_deck(id);
self.get_config_optional(key.as_str()) self.get_config_optional(key.as_str())
} }
pub(crate) fn set_last_notetype_for_deck( pub(crate) fn set_last_notetype_for_deck(
&mut self, &mut self,
did: DeckID, did: DeckId,
ntid: NoteTypeID, ntid: NoteTypeId,
) -> Result<()> { ) -> Result<()> {
let key = DeckConfigKey::LastNotetype.for_deck(did); let key = DeckConfigKey::LastNotetype.for_deck(did);
self.set_config(key.as_str(), &ntid) self.set_config(key.as_str(), &ntid)
} }
} }
fn build_aux_deck_key(deck: DeckID, key: &str) -> String { fn build_aux_deck_key(deck: DeckId, key: &str) -> String {
format!("_deck_{deck}_{key}", deck = deck, key = key) format!("_deck_{deck}_{key}", deck = deck, key = key)
} }

View File

@ -49,9 +49,9 @@ pub(crate) enum ConfigKey {
#[strum(to_string = "sortType")] #[strum(to_string = "sortType")]
BrowserSortKind, BrowserSortKind,
#[strum(to_string = "curDeck")] #[strum(to_string = "curDeck")]
CurrentDeckID, CurrentDeckId,
#[strum(to_string = "curModel")] #[strum(to_string = "curModel")]
CurrentNoteTypeID, CurrentNoteTypeId,
#[strum(to_string = "lastUnburied")] #[strum(to_string = "lastUnburied")]
LastUnburiedDay, LastUnburiedDay,
#[strum(to_string = "collapseTime")] #[strum(to_string = "collapseTime")]
@ -304,12 +304,12 @@ pub(crate) enum Weekday {
mod test { mod test {
use super::SortKind; use super::SortKind;
use crate::collection::open_test_collection; use crate::collection::open_test_collection;
use crate::decks::DeckID; use crate::decks::DeckId;
#[test] #[test]
fn defaults() { fn defaults() {
let col = open_test_collection(); let col = open_test_collection();
assert_eq!(col.get_current_deck_id(), DeckID(1)); assert_eq!(col.get_current_deck_id(), DeckId(1));
assert_eq!(col.get_browser_sort_kind(), SortKind::NoteField); assert_eq!(col.get_browser_sort_kind(), SortKind::NoteField);
} }

View File

@ -17,36 +17,36 @@ enum NoteTypeConfigKey {
} }
impl NoteTypeConfigKey { impl NoteTypeConfigKey {
fn for_notetype(self, ntid: NoteTypeID) -> String { fn for_notetype(self, ntid: NoteTypeId) -> String {
build_aux_notetype_key(ntid, <&'static str>::from(self)) build_aux_notetype_key(ntid, <&'static str>::from(self))
} }
} }
impl Collection { impl Collection {
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn get_current_notetype_id(&self) -> Option<NoteTypeID> { pub(crate) fn get_current_notetype_id(&self) -> Option<NoteTypeId> {
self.get_config_optional(ConfigKey::CurrentNoteTypeID) self.get_config_optional(ConfigKey::CurrentNoteTypeId)
} }
pub(crate) fn set_current_notetype_id(&mut self, ntid: NoteTypeID) -> Result<()> { pub(crate) fn set_current_notetype_id(&mut self, ntid: NoteTypeId) -> Result<()> {
self.set_config(ConfigKey::CurrentNoteTypeID, &ntid) self.set_config(ConfigKey::CurrentNoteTypeId, &ntid)
} }
pub(crate) fn clear_aux_config_for_notetype(&self, ntid: NoteTypeID) -> Result<()> { pub(crate) fn clear_aux_config_for_notetype(&self, ntid: NoteTypeId) -> Result<()> {
self.remove_config_prefix(&build_aux_notetype_key(ntid, "")) self.remove_config_prefix(&build_aux_notetype_key(ntid, ""))
} }
pub(crate) fn get_last_deck_added_to_for_notetype(&self, id: NoteTypeID) -> Option<DeckID> { pub(crate) fn get_last_deck_added_to_for_notetype(&self, id: NoteTypeId) -> Option<DeckId> {
let key = NoteTypeConfigKey::LastDeckAddedTo.for_notetype(id); let key = NoteTypeConfigKey::LastDeckAddedTo.for_notetype(id);
self.get_config_optional(key.as_str()) self.get_config_optional(key.as_str())
} }
pub(crate) fn set_last_deck_for_notetype(&mut self, id: NoteTypeID, did: DeckID) -> Result<()> { pub(crate) fn set_last_deck_for_notetype(&mut self, id: NoteTypeId, did: DeckId) -> Result<()> {
let key = NoteTypeConfigKey::LastDeckAddedTo.for_notetype(id); let key = NoteTypeConfigKey::LastDeckAddedTo.for_notetype(id);
self.set_config(key.as_str(), &did) self.set_config(key.as_str(), &did)
} }
} }
fn build_aux_notetype_key(ntid: NoteTypeID, key: &str) -> String { fn build_aux_notetype_key(ntid: NoteTypeId, key: &str) -> String {
format!("_nt_{ntid}_{key}", ntid = ntid, key = key) format!("_nt_{ntid}_{key}", ntid = ntid, key = key)
} }

View File

@ -4,10 +4,10 @@
use crate::{ use crate::{
collection::Collection, collection::Collection,
config::SchedulerVersion, config::SchedulerVersion,
err::{AnkiError, DBErrorKind, Result}, err::{AnkiError, DbErrorKind, Result},
i18n::I18n, i18n::I18n,
notetype::{ notetype::{
all_stock_notetypes, AlreadyGeneratedCardInfo, CardGenContext, NoteType, NoteTypeID, all_stock_notetypes, AlreadyGeneratedCardInfo, CardGenContext, NoteType, NoteTypeId,
NoteTypeKind, NoteTypeKind,
}, },
prelude::*, prelude::*,
@ -90,9 +90,9 @@ impl Collection {
debug!(self.log, "quick check"); debug!(self.log, "quick check");
if self.storage.quick_check_corrupt() { if self.storage.quick_check_corrupt() {
debug!(self.log, "quick check failed"); debug!(self.log, "quick check failed");
return Err(AnkiError::DBError { return Err(AnkiError::DbError {
info: self.tr.database_check_corrupt().into(), info: self.tr.database_check_corrupt().into(),
kind: DBErrorKind::Corrupt, kind: DbErrorKind::Corrupt,
}); });
} }
@ -283,14 +283,14 @@ impl Collection {
fn get_note_fixing_invalid_utf8( fn get_note_fixing_invalid_utf8(
&self, &self,
nid: NoteID, nid: NoteId,
out: &mut CheckDatabaseOutput, out: &mut CheckDatabaseOutput,
) -> Result<Note> { ) -> Result<Note> {
match self.storage.get_note(nid) { match self.storage.get_note(nid) {
Ok(note) => Ok(note.unwrap()), Ok(note) => Ok(note.unwrap()),
Err(err) => match err { Err(err) => match err {
AnkiError::DBError { AnkiError::DbError {
kind: DBErrorKind::Utf8, kind: DbErrorKind::Utf8,
.. ..
} => { } => {
// fix note then fetch again // fix note then fetch again
@ -343,7 +343,7 @@ impl Collection {
&mut self, &mut self,
stamp: TimestampMillis, stamp: TimestampMillis,
field_count: usize, field_count: usize,
previous_id: NoteTypeID, previous_id: NoteTypeId,
) -> Result<Arc<NoteType>> { ) -> Result<Arc<NoteType>> {
debug!(self.log, "create recovery notetype"); debug!(self.log, "create recovery notetype");
let extra_cards_required = self let extra_cards_required = self
@ -390,7 +390,7 @@ impl Collection {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::{collection::open_test_collection, decks::DeckID, search::SortMode}; use crate::{collection::open_test_collection, decks::DeckId, search::SortMode};
fn progress_fn(_progress: DatabaseCheckProgress, _throttle: bool) {} fn progress_fn(_progress: DatabaseCheckProgress, _throttle: bool) {}
@ -399,7 +399,7 @@ mod test {
let mut col = open_test_collection(); let mut col = open_test_collection();
let nt = col.get_notetype_by_name("Basic")?.unwrap(); let nt = col.get_notetype_by_name("Basic")?.unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
// card properties // card properties
col.storage col.storage
@ -430,7 +430,7 @@ mod test {
} }
); );
assert_eq!( assert_eq!(
col.storage.get_deck(DeckID(123))?.unwrap().name, col.storage.get_deck(DeckId(123))?.unwrap().name,
"recovered123" "recovered123"
); );
@ -484,7 +484,7 @@ mod test {
let mut col = open_test_collection(); let mut col = open_test_collection();
let nt = col.get_notetype_by_name("Basic")?.unwrap(); let nt = col.get_notetype_by_name("Basic")?.unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
// duplicate ordinals // duplicate ordinals
let cid = col.search_cards("", SortMode::NoOrder)?[0]; let cid = col.search_cards("", SortMode::NoOrder)?[0];
@ -533,7 +533,7 @@ mod test {
let mut col = open_test_collection(); let mut col = open_test_collection();
let nt = col.get_notetype_by_name("Basic")?.unwrap(); let nt = col.get_notetype_by_name("Basic")?.unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
// excess fields get joined into the last one // excess fields get joined into the last one
col.storage col.storage
@ -609,7 +609,7 @@ mod test {
let mut note = nt.new_note(); let mut note = nt.new_note();
note.tags.push("one".into()); note.tags.push("one".into());
note.tags.push("two".into()); note.tags.push("two".into());
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
col.set_tag_expanded("one", true)?; col.set_tag_expanded("one", true)?;

View File

@ -20,11 +20,11 @@ pub(crate) const INITIAL_EASE_FACTOR_THOUSANDS: u16 = (INITIAL_EASE_FACTOR * 100
mod schema11; mod schema11;
define_newtype!(DeckConfID, i64); define_newtype!(DeckConfId, i64);
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct DeckConf { pub struct DeckConf {
pub id: DeckConfID, pub id: DeckConfId,
pub name: String, pub name: String,
pub mtime_secs: TimestampSecs, pub mtime_secs: TimestampSecs,
pub usn: Usn, pub usn: Usn,
@ -34,7 +34,7 @@ pub struct DeckConf {
impl Default for DeckConf { impl Default for DeckConf {
fn default() -> Self { fn default() -> Self {
DeckConf { DeckConf {
id: DeckConfID(0), id: DeckConfId(0),
name: "".to_string(), name: "".to_string(),
mtime_secs: Default::default(), mtime_secs: Default::default(),
usn: Default::default(), usn: Default::default(),
@ -73,12 +73,12 @@ impl Default for DeckConf {
impl Collection { impl Collection {
/// If fallback is true, guaranteed to return a deck config. /// If fallback is true, guaranteed to return a deck config.
pub fn get_deck_config(&self, dcid: DeckConfID, fallback: bool) -> Result<Option<DeckConf>> { pub fn get_deck_config(&self, dcid: DeckConfId, fallback: bool) -> Result<Option<DeckConf>> {
if let Some(conf) = self.storage.get_deck_config(dcid)? { if let Some(conf) = self.storage.get_deck_config(dcid)? {
return Ok(Some(conf)); return Ok(Some(conf));
} }
if fallback { if fallback {
if let Some(conf) = self.storage.get_deck_config(DeckConfID(1))? { if let Some(conf) = self.storage.get_deck_config(DeckConfId(1))? {
return Ok(Some(conf)); return Ok(Some(conf));
} }
// if even the default deck config is missing, just return the defaults // if even the default deck config is missing, just return the defaults
@ -109,7 +109,7 @@ impl Collection {
} }
/// Remove a deck configuration. This will force a full sync. /// Remove a deck configuration. This will force a full sync.
pub(crate) fn remove_deck_config(&self, dcid: DeckConfID) -> Result<()> { pub(crate) fn remove_deck_config(&self, dcid: DeckConfId) -> Result<()> {
if dcid.0 == 1 { if dcid.0 == 1 {
return Err(AnkiError::invalid_input("can't delete default conf")); return Err(AnkiError::invalid_input("can't delete default conf"));
} }

View File

@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use super::{DeckConf, DeckConfID, INITIAL_EASE_FACTOR_THOUSANDS}; use super::{DeckConf, DeckConfId, INITIAL_EASE_FACTOR_THOUSANDS};
use crate::backend_proto::deck_config_inner::NewCardOrder; use crate::backend_proto::deck_config_inner::NewCardOrder;
use crate::backend_proto::DeckConfigInner; use crate::backend_proto::DeckConfigInner;
use crate::{serde::default_on_invalid, timestamp::TimestampSecs, types::Usn}; use crate::{serde::default_on_invalid, timestamp::TimestampSecs, types::Usn};
@ -16,7 +16,7 @@ use std::collections::HashMap;
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct DeckConfSchema11 { pub struct DeckConfSchema11 {
#[serde(deserialize_with = "deserialize_number_from_string")] #[serde(deserialize_with = "deserialize_number_from_string")]
pub(crate) id: DeckConfID, pub(crate) id: DeckConfId,
#[serde(rename = "mod", deserialize_with = "deserialize_number_from_string")] #[serde(rename = "mod", deserialize_with = "deserialize_number_from_string")]
pub(crate) mtime: TimestampSecs, pub(crate) mtime: TimestampSecs,
pub(crate) name: String, pub(crate) name: String,
@ -191,7 +191,7 @@ impl Default for LapseConfSchema11 {
impl Default for DeckConfSchema11 { impl Default for DeckConfSchema11 {
fn default() -> Self { fn default() -> Self {
DeckConfSchema11 { DeckConfSchema11 {
id: DeckConfID(0), id: DeckConfId(0),
mtime: TimestampSecs(0), mtime: TimestampSecs(0),
name: "Default".to_string(), name: "Default".to_string(),
usn: Usn(0), usn: Usn(0),

View File

@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{collection::Collection, decks::DeckID, err::Result}; use crate::{collection::Collection, decks::DeckId, err::Result};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]
@ -18,7 +18,7 @@ impl Collection {
days_elapsed: u32, days_elapsed: u32,
learn_cutoff: u32, learn_cutoff: u32,
limit_to: Option<&str>, limit_to: Option<&str>,
) -> Result<HashMap<DeckID, DueCounts>> { ) -> Result<HashMap<DeckId, DueCounts>> {
self.storage.due_counts( self.storage.due_counts(
self.scheduler_version(), self.scheduler_version(),
days_elapsed, days_elapsed,

View File

@ -24,7 +24,7 @@ impl Deck {
filt.preview_delay = 10; filt.preview_delay = 10;
filt.reschedule = true; filt.reschedule = true;
Deck { Deck {
id: DeckID(0), id: DeckId(0),
name: "".into(), name: "".into(),
mtime_secs: TimestampSecs(0), mtime_secs: TimestampSecs(0),
usn: Usn(0), usn: Usn(0),

View File

@ -15,7 +15,7 @@ pub use crate::backend_proto::{
use crate::{backend_proto as pb, markdown::render_markdown, text::sanitize_html_no_images}; use crate::{backend_proto as pb, markdown::render_markdown, text::sanitize_html_no_images};
use crate::{ use crate::{
collection::Collection, collection::Collection,
deckconf::DeckConfID, deckconf::DeckConfId,
define_newtype, define_newtype,
err::{AnkiError, Result}, err::{AnkiError, Result},
prelude::*, prelude::*,
@ -27,11 +27,11 @@ pub(crate) use counts::DueCounts;
pub use schema11::DeckSchema11; pub use schema11::DeckSchema11;
use std::{borrow::Cow, sync::Arc}; use std::{borrow::Cow, sync::Arc};
define_newtype!(DeckID, i64); define_newtype!(DeckId, i64);
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Deck { pub struct Deck {
pub id: DeckID, pub id: DeckId,
pub name: String, pub name: String,
pub mtime_secs: TimestampSecs, pub mtime_secs: TimestampSecs,
pub usn: Usn, pub usn: Usn,
@ -42,7 +42,7 @@ pub struct Deck {
impl Deck { impl Deck {
pub fn new_normal() -> Deck { pub fn new_normal() -> Deck {
Deck { Deck {
id: DeckID(0), id: DeckId(0),
name: "".into(), name: "".into(),
mtime_secs: TimestampSecs(0), mtime_secs: TimestampSecs(0),
usn: Usn(0), usn: Usn(0),
@ -72,9 +72,9 @@ impl Deck {
} }
/// Returns deck config ID if deck is a normal deck. /// Returns deck config ID if deck is a normal deck.
pub(crate) fn config_id(&self) -> Option<DeckConfID> { pub(crate) fn config_id(&self) -> Option<DeckConfId> {
if let DeckKind::Normal(ref norm) = self.kind { if let DeckKind::Normal(ref norm) = self.kind {
Some(DeckConfID(norm.config_id)) Some(DeckConfId(norm.config_id))
} else { } else {
None None
} }
@ -197,7 +197,7 @@ pub(crate) fn human_deck_name_to_native(name: &str) -> String {
} }
impl Collection { impl Collection {
pub(crate) fn get_deck(&mut self, did: DeckID) -> Result<Option<Arc<Deck>>> { pub(crate) fn get_deck(&mut self, did: DeckId) -> Result<Option<Arc<Deck>>> {
if let Some(deck) = self.state.deck_cache.get(&did) { if let Some(deck) = self.state.deck_cache.get(&did) {
return Ok(Some(deck.clone())); return Ok(Some(deck.clone()));
} }
@ -259,7 +259,7 @@ pub(crate) fn reparented_name(dragged: &str, dropped: Option<&str>) -> Option<St
impl Collection { impl Collection {
pub(crate) fn default_deck_is_empty(&self) -> Result<bool> { pub(crate) fn default_deck_is_empty(&self) -> Result<bool> {
self.storage.deck_is_empty(DeckID(1)) self.storage.deck_is_empty(DeckId(1))
} }
/// Normalize deck name and rename if not unique. Bumps mtime and usn if /// Normalize deck name and rename if not unique. Bumps mtime and usn if
@ -307,7 +307,7 @@ impl Collection {
}) })
} }
pub fn rename_deck(&mut self, did: DeckID, new_human_name: &str) -> Result<OpOutput<()>> { pub fn rename_deck(&mut self, did: DeckId, new_human_name: &str) -> Result<OpOutput<()>> {
self.transact(Op::RenameDeck, |col| { self.transact(Op::RenameDeck, |col| {
let existing_deck = col.storage.get_deck(did)?.ok_or(AnkiError::NotFound)?; let existing_deck = col.storage.get_deck(did)?.ok_or(AnkiError::NotFound)?;
let mut deck = existing_deck.clone(); let mut deck = existing_deck.clone();
@ -368,7 +368,7 @@ impl Collection {
Ok(()) Ok(())
} }
pub(crate) fn recover_missing_deck(&mut self, did: DeckID, usn: Usn) -> Result<()> { pub(crate) fn recover_missing_deck(&mut self, did: DeckId, usn: Usn) -> Result<()> {
let mut deck = Deck::new_normal(); let mut deck = Deck::new_normal();
deck.id = did; deck.id = did;
deck.name = format!("recovered{}", did); deck.name = format!("recovered{}", did);
@ -474,12 +474,12 @@ impl Collection {
/// Get a deck based on its human name. If you have a machine name, /// Get a deck based on its human name. If you have a machine name,
/// use the method in storage instead. /// use the method in storage instead.
pub(crate) fn get_deck_id(&self, human_name: &str) -> Result<Option<DeckID>> { pub(crate) fn get_deck_id(&self, human_name: &str) -> Result<Option<DeckId>> {
let machine_name = human_deck_name_to_native(&human_name); let machine_name = human_deck_name_to_native(&human_name);
self.storage.get_deck_id(&machine_name) self.storage.get_deck_id(&machine_name)
} }
pub fn remove_decks_and_child_decks(&mut self, dids: &[DeckID]) -> Result<OpOutput<usize>> { pub fn remove_decks_and_child_decks(&mut self, dids: &[DeckId]) -> Result<OpOutput<usize>> {
self.transact(Op::RemoveDeck, |col| { self.transact(Op::RemoveDeck, |col| {
let mut card_count = 0; let mut card_count = 0;
let usn = col.usn()?; let usn = col.usn()?;
@ -521,13 +521,13 @@ impl Collection {
Ok(card_count) Ok(card_count)
} }
fn delete_all_cards_in_normal_deck(&mut self, did: DeckID) -> Result<usize> { fn delete_all_cards_in_normal_deck(&mut self, did: DeckId) -> Result<usize> {
let cids = self.storage.all_cards_in_single_deck(did)?; let cids = self.storage.all_cards_in_single_deck(did)?;
self.remove_cards_and_orphaned_notes(&cids)?; self.remove_cards_and_orphaned_notes(&cids)?;
Ok(cids.len()) Ok(cids.len())
} }
pub fn get_all_deck_names(&self, skip_empty_default: bool) -> Result<Vec<(DeckID, String)>> { pub fn get_all_deck_names(&self, skip_empty_default: bool) -> Result<Vec<(DeckId, String)>> {
if skip_empty_default && self.default_deck_is_empty()? { if skip_empty_default && self.default_deck_is_empty()? {
Ok(self Ok(self
.storage .storage
@ -540,7 +540,7 @@ impl Collection {
} }
} }
pub fn get_all_normal_deck_names(&mut self) -> Result<Vec<(DeckID, String)>> { pub fn get_all_normal_deck_names(&mut self) -> Result<Vec<(DeckId, String)>> {
Ok(self Ok(self
.storage .storage
.get_all_deck_names()? .get_all_deck_names()?
@ -582,7 +582,7 @@ impl Collection {
&mut self, &mut self,
today: u32, today: u32,
usn: Usn, usn: Usn,
did: DeckID, did: DeckId,
new_delta: i32, new_delta: i32,
review_delta: i32, review_delta: i32,
) -> Result<()> { ) -> Result<()> {
@ -605,7 +605,7 @@ impl Collection {
pub(crate) fn counts_for_deck_today( pub(crate) fn counts_for_deck_today(
&mut self, &mut self,
did: DeckID, did: DeckId,
) -> Result<pb::CountsForDeckTodayOut> { ) -> Result<pb::CountsForDeckTodayOut> {
let today = self.current_due_day(0)?; let today = self.current_due_day(0)?;
let mut deck = self.storage.get_deck(did)?.ok_or(AnkiError::NotFound)?; let mut deck = self.storage.get_deck(did)?.ok_or(AnkiError::NotFound)?;
@ -635,8 +635,8 @@ impl Collection {
pub fn reparent_decks( pub fn reparent_decks(
&mut self, &mut self,
deck_ids: &[DeckID], deck_ids: &[DeckId],
new_parent: Option<DeckID>, new_parent: Option<DeckId>,
) -> Result<OpOutput<usize>> { ) -> Result<OpOutput<usize>> {
self.transact(Op::ReparentDeck, |col| { self.transact(Op::ReparentDeck, |col| {
col.reparent_decks_inner(deck_ids, new_parent) col.reparent_decks_inner(deck_ids, new_parent)
@ -645,8 +645,8 @@ impl Collection {
pub fn reparent_decks_inner( pub fn reparent_decks_inner(
&mut self, &mut self,
deck_ids: &[DeckID], deck_ids: &[DeckId],
new_parent: Option<DeckID>, new_parent: Option<DeckId>,
) -> Result<usize> { ) -> Result<usize> {
let usn = self.usn()?; let usn = self.usn()?;
let target_deck; let target_deck;

View File

@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use super::DeckID; use super::DeckId;
use super::{ use super::{
human_deck_name_to_native, Deck, DeckCommon, DeckKind, FilteredDeck, FilteredSearchTerm, human_deck_name_to_native, Deck, DeckCommon, DeckKind, FilteredDeck, FilteredSearchTerm,
NormalDeck, NormalDeck,
@ -82,7 +82,7 @@ fn is_false(b: &bool) -> bool {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct DeckCommonSchema11 { pub struct DeckCommonSchema11 {
#[serde(deserialize_with = "deserialize_number_from_string")] #[serde(deserialize_with = "deserialize_number_from_string")]
pub(crate) id: DeckID, pub(crate) id: DeckId,
#[serde( #[serde(
rename = "mod", rename = "mod",
deserialize_with = "deserialize_number_from_string", deserialize_with = "deserialize_number_from_string",
@ -195,7 +195,7 @@ impl DeckSchema11 {
// } // }
// } // }
pub fn id(&self) -> DeckID { pub fn id(&self) -> DeckId {
self.common().id self.common().id
} }
@ -214,7 +214,7 @@ impl Default for NormalDeckSchema11 {
fn default() -> Self { fn default() -> Self {
NormalDeckSchema11 { NormalDeckSchema11 {
common: DeckCommonSchema11 { common: DeckCommonSchema11 {
id: DeckID(0), id: DeckId(0),
mtime: TimestampSecs(0), mtime: TimestampSecs(0),
name: "".to_string(), name: "".to_string(),
usn: Usn(0), usn: Usn(0),

View File

@ -6,8 +6,8 @@ use crate::{
backend_proto::DeckTreeNode, backend_proto::DeckTreeNode,
collection::Collection, collection::Collection,
config::{BoolKey, SchedulerVersion}, config::{BoolKey, SchedulerVersion},
deckconf::{DeckConf, DeckConfID}, deckconf::{DeckConf, DeckConfId},
decks::DeckID, decks::DeckId,
err::Result, err::Result,
timestamp::TimestampSecs, timestamp::TimestampSecs,
}; };
@ -18,7 +18,7 @@ use std::{
}; };
use unicase::UniCase; use unicase::UniCase;
fn deck_names_to_tree(names: Vec<(DeckID, String)>) -> DeckTreeNode { fn deck_names_to_tree(names: Vec<(DeckId, String)>) -> DeckTreeNode {
let mut top = DeckTreeNode::default(); let mut top = DeckTreeNode::default();
let mut it = names.into_iter().peekable(); let mut it = names.into_iter().peekable();
@ -28,7 +28,7 @@ fn deck_names_to_tree(names: Vec<(DeckID, String)>) -> DeckTreeNode {
} }
fn add_child_nodes( fn add_child_nodes(
names: &mut Peekable<impl Iterator<Item = (DeckID, String)>>, names: &mut Peekable<impl Iterator<Item = (DeckId, String)>>,
parent: &mut DeckTreeNode, parent: &mut DeckTreeNode,
) { ) {
while let Some((id, name)) = names.peek() { while let Some((id, name)) = names.peek() {
@ -64,10 +64,10 @@ fn add_child_nodes(
fn add_collapsed_and_filtered( fn add_collapsed_and_filtered(
node: &mut DeckTreeNode, node: &mut DeckTreeNode,
decks: &HashMap<DeckID, Deck>, decks: &HashMap<DeckId, Deck>,
browser: bool, browser: bool,
) { ) {
if let Some(deck) = decks.get(&DeckID(node.deck_id)) { if let Some(deck) = decks.get(&DeckId(node.deck_id)) {
node.collapsed = if browser { node.collapsed = if browser {
deck.common.browser_collapsed deck.common.browser_collapsed
} else { } else {
@ -80,8 +80,8 @@ fn add_collapsed_and_filtered(
} }
} }
fn add_counts(node: &mut DeckTreeNode, counts: &HashMap<DeckID, DueCounts>) { fn add_counts(node: &mut DeckTreeNode, counts: &HashMap<DeckId, DueCounts>) {
if let Some(counts) = counts.get(&DeckID(node.deck_id)) { if let Some(counts) = counts.get(&DeckId(node.deck_id)) {
node.new_count = counts.new; node.new_count = counts.new;
node.review_count = counts.review; node.review_count = counts.review;
node.learn_count = counts.learning; node.learn_count = counts.learning;
@ -96,12 +96,12 @@ fn add_counts(node: &mut DeckTreeNode, counts: &HashMap<DeckID, DueCounts>) {
fn apply_limits( fn apply_limits(
node: &mut DeckTreeNode, node: &mut DeckTreeNode,
today: u32, today: u32,
decks: &HashMap<DeckID, Deck>, decks: &HashMap<DeckId, Deck>,
dconf: &HashMap<DeckConfID, DeckConf>, dconf: &HashMap<DeckConfId, DeckConf>,
parent_limits: (u32, u32), parent_limits: (u32, u32),
) { ) {
let (mut remaining_new, mut remaining_rev) = let (mut remaining_new, mut remaining_rev) =
remaining_counts_for_deck(DeckID(node.deck_id), today, decks, dconf); remaining_counts_for_deck(DeckId(node.deck_id), today, decks, dconf);
// cap remaining to parent limits // cap remaining to parent limits
remaining_new = remaining_new.min(parent_limits.0); remaining_new = remaining_new.min(parent_limits.0);
@ -130,14 +130,14 @@ fn apply_limits(
fn apply_limits_v2_old( fn apply_limits_v2_old(
node: &mut DeckTreeNode, node: &mut DeckTreeNode,
today: u32, today: u32,
decks: &HashMap<DeckID, Deck>, decks: &HashMap<DeckId, Deck>,
dconf: &HashMap<DeckConfID, DeckConf>, dconf: &HashMap<DeckConfId, DeckConf>,
parent_limits: (u32, u32), parent_limits: (u32, u32),
) -> u32 { ) -> u32 {
let original_rev_count = node.review_count; let original_rev_count = node.review_count;
let (mut remaining_new, remaining_rev) = let (mut remaining_new, remaining_rev) =
remaining_counts_for_deck(DeckID(node.deck_id), today, decks, dconf); remaining_counts_for_deck(DeckId(node.deck_id), today, decks, dconf);
// cap remaining to parent limits // cap remaining to parent limits
remaining_new = remaining_new.min(parent_limits.0); remaining_new = remaining_new.min(parent_limits.0);
@ -161,18 +161,18 @@ fn apply_limits_v2_old(
} }
fn remaining_counts_for_deck( fn remaining_counts_for_deck(
did: DeckID, did: DeckId,
today: u32, today: u32,
decks: &HashMap<DeckID, Deck>, decks: &HashMap<DeckId, Deck>,
dconf: &HashMap<DeckConfID, DeckConf>, dconf: &HashMap<DeckConfId, DeckConf>,
) -> (u32, u32) { ) -> (u32, u32) {
if let Some(deck) = decks.get(&did) { if let Some(deck) = decks.get(&did) {
match &deck.kind { match &deck.kind {
DeckKind::Normal(norm) => { DeckKind::Normal(norm) => {
let (new_today, rev_today) = deck.new_rev_counts(today); let (new_today, rev_today) = deck.new_rev_counts(today);
if let Some(conf) = dconf if let Some(conf) = dconf
.get(&DeckConfID(norm.config_id)) .get(&DeckConfId(norm.config_id))
.or_else(|| dconf.get(&DeckConfID(1))) .or_else(|| dconf.get(&DeckConfId(1)))
{ {
let new = (conf.inner.new_per_day as i32) let new = (conf.inner.new_per_day as i32)
.saturating_sub(new_today) .saturating_sub(new_today)
@ -212,7 +212,7 @@ fn hide_default_deck(node: &mut DeckTreeNode) {
} }
} }
fn get_subnode(top: DeckTreeNode, target: DeckID) -> Option<DeckTreeNode> { fn get_subnode(top: DeckTreeNode, target: DeckId) -> Option<DeckTreeNode> {
if top.deck_id == target.0 { if top.deck_id == target.0 {
return Some(top); return Some(top);
} }
@ -257,7 +257,7 @@ impl Collection {
pub fn deck_tree( pub fn deck_tree(
&mut self, &mut self,
now: Option<TimestampSecs>, now: Option<TimestampSecs>,
top_deck_id: Option<DeckID>, top_deck_id: Option<DeckId>,
) -> Result<DeckTreeNode> { ) -> Result<DeckTreeNode> {
let names = self.storage.get_all_deck_names()?; let names = self.storage.get_all_deck_names()?;
let mut tree = deck_names_to_tree(names); let mut tree = deck_names_to_tree(names);
@ -317,7 +317,7 @@ impl Collection {
Ok(LegacyDueCounts::from(tree)) Ok(LegacyDueCounts::from(tree))
} }
pub(crate) fn add_missing_deck_names(&mut self, names: &[(DeckID, String)]) -> Result<usize> { pub(crate) fn add_missing_deck_names(&mut self, names: &[(DeckId, String)]) -> Result<usize> {
let mut parents = HashSet::new(); let mut parents = HashSet::new();
let mut missing = 0; let mut missing = 0;
for (_id, name) in names { for (_id, name) in names {
@ -338,7 +338,7 @@ impl Collection {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::{collection::open_test_collection, deckconf::DeckConfID, err::Result}; use crate::{collection::open_test_collection, deckconf::DeckConfId, err::Result};
#[test] #[test]
fn wellformed() -> Result<()> { fn wellformed() -> Result<()> {
@ -410,7 +410,7 @@ mod test {
assert_eq!(tree.children[0].children[0].new_count, 4); assert_eq!(tree.children[0].children[0].new_count, 4);
// set the limit to 4, which should mean 3 are left // set the limit to 4, which should mean 3 are left
let mut conf = col.get_deck_config(DeckConfID(1), false)?.unwrap(); let mut conf = col.get_deck_config(DeckConfId(1), false)?.unwrap();
conf.inner.new_per_day = 4; conf.inner.new_per_day = 4;
col.add_or_update_deck_config(&mut conf, false)?; col.add_or_update_deck_config(&mut conf, false)?;

View File

@ -9,8 +9,8 @@ pub(crate) enum UndoableDeckChange {
Added(Box<Deck>), Added(Box<Deck>),
Updated(Box<Deck>), Updated(Box<Deck>),
Removed(Box<Deck>), Removed(Box<Deck>),
GraveAdded(Box<(DeckID, Usn)>), GraveAdded(Box<(DeckId, Usn)>),
GraveRemoved(Box<(DeckID, Usn)>), GraveRemoved(Box<(DeckId, Usn)>),
} }
impl Collection { impl Collection {
@ -84,12 +84,12 @@ impl Collection {
Ok(()) Ok(())
} }
fn add_deck_grave_undoable(&mut self, did: DeckID, usn: Usn) -> Result<()> { fn add_deck_grave_undoable(&mut self, did: DeckId, usn: Usn) -> Result<()> {
self.save_undo(UndoableDeckChange::GraveAdded(Box::new((did, usn)))); self.save_undo(UndoableDeckChange::GraveAdded(Box::new((did, usn))));
self.storage.add_deck_grave(did, usn) self.storage.add_deck_grave(did, usn)
} }
fn remove_deck_grave(&mut self, did: DeckID, usn: Usn) -> Result<()> { fn remove_deck_grave(&mut self, did: DeckId, usn: Usn) -> Result<()> {
self.save_undo(UndoableDeckChange::GraveRemoved(Box::new((did, usn)))); self.save_undo(UndoableDeckChange::GraveRemoved(Box::new((did, usn))));
self.storage.remove_deck_grave(did) self.storage.remove_deck_grave(did)
} }

View File

@ -22,10 +22,10 @@ pub enum AnkiError {
TemplateSaveError { ordinal: usize }, TemplateSaveError { ordinal: usize },
#[fail(display = "I/O error: {}", info)] #[fail(display = "I/O error: {}", info)]
IOError { info: String }, IoError { info: String },
#[fail(display = "DB error: {}", info)] #[fail(display = "DB error: {}", info)]
DBError { info: String, kind: DBErrorKind }, DbError { info: String, kind: DbErrorKind },
#[fail(display = "Network error: {:?} {}", kind, info)] #[fail(display = "Network error: {:?} {}", kind, info)]
NetworkError { NetworkError {
@ -37,7 +37,7 @@ pub enum AnkiError {
SyncError { info: String, kind: SyncErrorKind }, SyncError { info: String, kind: SyncErrorKind },
#[fail(display = "JSON encode/decode error: {}", info)] #[fail(display = "JSON encode/decode error: {}", info)]
JSONError { info: String }, JsonError { info: String },
#[fail(display = "Protobuf encode/decode error: {}", info)] #[fail(display = "Protobuf encode/decode error: {}", info)]
ProtoError { info: String }, ProtoError { info: String },
@ -123,9 +123,9 @@ impl AnkiError {
AnkiError::TemplateSaveError { ordinal } => tr AnkiError::TemplateSaveError { ordinal } => tr
.card_templates_invalid_template_number(ordinal + 1) .card_templates_invalid_template_number(ordinal + 1)
.into(), .into(),
AnkiError::DBError { info, kind } => match kind { AnkiError::DbError { info, kind } => match kind {
DBErrorKind::Corrupt => info.clone(), DbErrorKind::Corrupt => info.clone(),
DBErrorKind::Locked => "Anki already open, or media currently syncing.".into(), DbErrorKind::Locked => "Anki already open, or media currently syncing.".into(),
_ => format!("{:?}", self), _ => format!("{:?}", self),
}, },
AnkiError::SearchError(kind) => { AnkiError::SearchError(kind) => {
@ -220,7 +220,7 @@ pub enum TemplateError {
impl From<io::Error> for AnkiError { impl From<io::Error> for AnkiError {
fn from(err: io::Error) -> Self { fn from(err: io::Error) -> Self {
AnkiError::IOError { AnkiError::IoError {
info: format!("{:?}", err), info: format!("{:?}", err),
} }
} }
@ -230,18 +230,18 @@ impl From<rusqlite::Error> for AnkiError {
fn from(err: rusqlite::Error) -> Self { fn from(err: rusqlite::Error) -> Self {
if let rusqlite::Error::SqliteFailure(error, Some(reason)) = &err { if let rusqlite::Error::SqliteFailure(error, Some(reason)) = &err {
if error.code == rusqlite::ErrorCode::DatabaseBusy { if error.code == rusqlite::ErrorCode::DatabaseBusy {
return AnkiError::DBError { return AnkiError::DbError {
info: "".to_string(), info: "".to_string(),
kind: DBErrorKind::Locked, kind: DbErrorKind::Locked,
}; };
} }
if reason.contains("regex parse error") { if reason.contains("regex parse error") {
return AnkiError::SearchError(SearchErrorKind::Regex(reason.to_owned())); return AnkiError::SearchError(SearchErrorKind::Regex(reason.to_owned()));
} }
} }
AnkiError::DBError { AnkiError::DbError {
info: format!("{:?}", err), info: format!("{:?}", err),
kind: DBErrorKind::Other, kind: DbErrorKind::Other,
} }
} }
} }
@ -250,15 +250,15 @@ impl From<rusqlite::types::FromSqlError> for AnkiError {
fn from(err: rusqlite::types::FromSqlError) -> Self { fn from(err: rusqlite::types::FromSqlError) -> Self {
if let rusqlite::types::FromSqlError::Other(ref err) = err { if let rusqlite::types::FromSqlError::Other(ref err) = err {
if let Some(_err) = err.downcast_ref::<Utf8Error>() { if let Some(_err) = err.downcast_ref::<Utf8Error>() {
return AnkiError::DBError { return AnkiError::DbError {
info: "".to_string(), info: "".to_string(),
kind: DBErrorKind::Utf8, kind: DbErrorKind::Utf8,
}; };
} }
} }
AnkiError::DBError { AnkiError::DbError {
info: format!("{:?}", err), info: format!("{:?}", err),
kind: DBErrorKind::Other, kind: DbErrorKind::Other,
} }
} }
} }
@ -373,7 +373,7 @@ impl From<zip::result::ZipError> for AnkiError {
impl From<serde_json::Error> for AnkiError { impl From<serde_json::Error> for AnkiError {
fn from(err: serde_json::Error) -> Self { fn from(err: serde_json::Error) -> Self {
AnkiError::JSONError { AnkiError::JsonError {
info: err.to_string(), info: err.to_string(),
} }
} }
@ -396,7 +396,7 @@ impl From<prost::DecodeError> for AnkiError {
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum DBErrorKind { pub enum DbErrorKind {
FileTooNew, FileTooNew,
FileTooOld, FileTooOld,
MissingEntity, MissingEntity,
@ -408,7 +408,7 @@ pub enum DBErrorKind {
impl From<PathPersistError> for AnkiError { impl From<PathPersistError> for AnkiError {
fn from(e: PathPersistError) -> Self { fn from(e: PathPersistError) -> Self {
AnkiError::IOError { AnkiError::IoError {
info: e.to_string(), info: e.to_string(),
} }
} }

View File

@ -4,7 +4,7 @@
use crate::{ use crate::{
collection::Collection, collection::Collection,
err::{AnkiError, Result}, err::{AnkiError, Result},
notes::{NoteID, TransformNoteOutput}, notes::{NoteId, TransformNoteOutput},
prelude::*, prelude::*,
text::normalize_to_nfc, text::normalize_to_nfc,
}; };
@ -12,7 +12,7 @@ use regex::Regex;
use std::borrow::Cow; use std::borrow::Cow;
pub struct FindReplaceContext { pub struct FindReplaceContext {
nids: Vec<NoteID>, nids: Vec<NoteId>,
search: Regex, search: Regex,
replacement: String, replacement: String,
field_name: Option<String>, field_name: Option<String>,
@ -20,7 +20,7 @@ pub struct FindReplaceContext {
impl FindReplaceContext { impl FindReplaceContext {
pub fn new( pub fn new(
nids: Vec<NoteID>, nids: Vec<NoteId>,
search_re: &str, search_re: &str,
repl: impl Into<String>, repl: impl Into<String>,
field_name: Option<String>, field_name: Option<String>,
@ -41,7 +41,7 @@ impl FindReplaceContext {
impl Collection { impl Collection {
pub fn find_and_replace( pub fn find_and_replace(
&mut self, &mut self,
nids: Vec<NoteID>, nids: Vec<NoteId>,
search_re: &str, search_re: &str,
repl: &str, repl: &str,
field_name: Option<String>, field_name: Option<String>,
@ -101,7 +101,7 @@ impl Collection {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::{collection::open_test_collection, decks::DeckID}; use crate::{collection::open_test_collection, decks::DeckId};
#[test] #[test]
fn findreplace() -> Result<()> { fn findreplace() -> Result<()> {
@ -111,12 +111,12 @@ mod test {
let mut note = nt.new_note(); let mut note = nt.new_note();
note.set_field(0, "one aaa")?; note.set_field(0, "one aaa")?;
note.set_field(1, "two aaa")?; note.set_field(1, "two aaa")?;
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
let nt = col.get_notetype_by_name("Cloze")?.unwrap(); let nt = col.get_notetype_by_name("Cloze")?.unwrap();
let mut note2 = nt.new_note(); let mut note2 = nt.new_note();
note2.set_field(0, "three aaa")?; note2.set_field(0, "three aaa")?;
col.add_note(&mut note2, DeckID(1))?; col.add_note(&mut note2, DeckId(1))?;
let nids = col.search_notes("")?; let nids = col.search_notes("")?;
let out = col.find_and_replace(nids.clone(), "(?i)AAA", "BBB", None)?; let out = col.find_and_replace(nids.clone(), "(?i)AAA", "BBB", None)?;

View File

@ -151,7 +151,7 @@ where
} }
// add entry to the list // add entry to the list
let data = sha1_of_file(&dentry.path()).map_err(|e| AnkiError::IOError { let data = sha1_of_file(&dentry.path()).map_err(|e| AnkiError::IoError {
info: format!("unable to read {}: {}", fname, e), info: format!("unable to read {}: {}", fname, e),
})?; })?;
let sha1 = Some(data); let sha1 = Some(data);

View File

@ -2,7 +2,7 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::collection::Collection; use crate::collection::Collection;
use crate::err::{AnkiError, DBErrorKind, Result}; use crate::err::{AnkiError, DbErrorKind, Result};
use crate::latex::extract_latex_expanding_clozes; use crate::latex::extract_latex_expanding_clozes;
use crate::log::debug; use crate::log::debug;
use crate::media::database::MediaDatabaseContext; use crate::media::database::MediaDatabaseContext;
@ -362,9 +362,9 @@ where
let mut note = self.ctx.storage.get_note(nid)?.unwrap(); let mut note = self.ctx.storage.get_note(nid)?.unwrap();
let nt = note_types let nt = note_types
.get(&note.notetype_id) .get(&note.notetype_id)
.ok_or_else(|| AnkiError::DBError { .ok_or_else(|| AnkiError::DbError {
info: "missing note type".to_string(), info: "missing note type".to_string(),
kind: DBErrorKind::MissingEntity, kind: DbErrorKind::MissingEntity,
})?; })?;
if fix_and_extract_media_refs( if fix_and_extract_media_refs(
&mut note, &mut note,

View File

@ -412,7 +412,7 @@ pub(super) fn data_for_file(media_folder: &Path, fname: &str) -> Result<Option<V
if e.kind() == io::ErrorKind::NotFound { if e.kind() == io::ErrorKind::NotFound {
return Ok(None); return Ok(None);
} else { } else {
return Err(AnkiError::IOError { return Err(AnkiError::IoError {
info: format!("unable to read {}: {}", fname, e), info: format!("unable to read {}: {}", fname, e),
}); });
} }

View File

@ -64,9 +64,9 @@ struct SyncBeginResponse {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum LocalState { enum LocalState {
NotInDB, NotInDb,
InDBNotPending, InDbNotPending,
InDBAndPending, InDbAndPending,
} }
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
@ -468,17 +468,17 @@ fn determine_required_change(
match (local_sha1, remote_sha1, local_state) { match (local_sha1, remote_sha1, local_state) {
// both deleted, not in local DB // both deleted, not in local DB
("", "", L::NotInDB) => R::None, ("", "", L::NotInDb) => R::None,
// both deleted, in local DB // both deleted, in local DB
("", "", _) => R::Delete, ("", "", _) => R::Delete,
// added on server, add even if local deletion pending // added on server, add even if local deletion pending
("", _, _) => R::Download, ("", _, _) => R::Download,
// deleted on server but added locally; upload later // deleted on server but added locally; upload later
(_, "", L::InDBAndPending) => R::None, (_, "", L::InDbAndPending) => R::None,
// deleted on server and not pending sync // deleted on server and not pending sync
(_, "", _) => R::Delete, (_, "", _) => R::Delete,
// if pending but the same as server, don't need to upload // if pending but the same as server, don't need to upload
(lsum, rsum, L::InDBAndPending) if lsum == rsum => R::RemovePending, (lsum, rsum, L::InDbAndPending) if lsum == rsum => R::RemovePending,
(lsum, rsum, _) => { (lsum, rsum, _) => {
if lsum == rsum { if lsum == rsum {
// not pending and same as server, nothing to do // not pending and same as server, nothing to do
@ -510,12 +510,12 @@ fn determine_required_changes<'a>(
None => "".to_string(), None => "".to_string(),
}, },
if entry.sync_required { if entry.sync_required {
LocalState::InDBAndPending LocalState::InDbAndPending
} else { } else {
LocalState::InDBNotPending LocalState::InDbNotPending
}, },
), ),
None => ("".to_string(), LocalState::NotInDB), None => ("".to_string(), LocalState::NotInDb),
}; };
let req_change = determine_required_change(&local_sha1, &remote.sha1, local_state); let req_change = determine_required_change(&local_sha1, &remote.sha1, local_state);
@ -855,14 +855,14 @@ mod test {
use determine_required_change as d; use determine_required_change as d;
use LocalState as L; use LocalState as L;
use RequiredChange as R; use RequiredChange as R;
assert_eq!(d("", "", L::NotInDB), R::None); assert_eq!(d("", "", L::NotInDb), R::None);
assert_eq!(d("", "", L::InDBNotPending), R::Delete); assert_eq!(d("", "", L::InDbNotPending), R::Delete);
assert_eq!(d("", "1", L::InDBAndPending), R::Download); assert_eq!(d("", "1", L::InDbAndPending), R::Download);
assert_eq!(d("1", "", L::InDBAndPending), R::None); assert_eq!(d("1", "", L::InDbAndPending), R::None);
assert_eq!(d("1", "", L::InDBNotPending), R::Delete); assert_eq!(d("1", "", L::InDbNotPending), R::Delete);
assert_eq!(d("1", "1", L::InDBNotPending), R::None); assert_eq!(d("1", "1", L::InDbNotPending), R::None);
assert_eq!(d("1", "1", L::InDBAndPending), R::RemovePending); assert_eq!(d("1", "1", L::InDbAndPending), R::RemovePending);
assert_eq!(d("a", "b", L::InDBAndPending), R::Download); assert_eq!(d("a", "b", L::InDbAndPending), R::Download);
assert_eq!(d("a", "b", L::InDBNotPending), R::Download); assert_eq!(d("a", "b", L::InDbNotPending), R::Download);
} }
} }

View File

@ -5,10 +5,10 @@ pub(crate) mod undo;
use crate::{ use crate::{
backend_proto as pb, backend_proto as pb,
decks::DeckID, decks::DeckId,
define_newtype, define_newtype,
err::{AnkiError, Result}, err::{AnkiError, Result},
notetype::{CardGenContext, NoteField, NoteType, NoteTypeID}, notetype::{CardGenContext, NoteField, NoteType, NoteTypeId},
prelude::*, prelude::*,
template::field_is_empty, template::field_is_empty,
text::{ensure_string_in_nfc, normalize_to_nfc, strip_html_preserving_media_filenames}, text::{ensure_string_in_nfc, normalize_to_nfc, strip_html_preserving_media_filenames},
@ -26,7 +26,7 @@ use std::{
convert::TryInto, convert::TryInto,
}; };
define_newtype!(NoteID, i64); define_newtype!(NoteId, i64);
#[derive(Default)] #[derive(Default)]
pub(crate) struct TransformNoteOutput { pub(crate) struct TransformNoteOutput {
@ -37,9 +37,9 @@ pub(crate) struct TransformNoteOutput {
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Note { pub struct Note {
pub id: NoteID, pub id: NoteId,
pub guid: String, pub guid: String,
pub notetype_id: NoteTypeID, pub notetype_id: NoteTypeId,
pub mtime: TimestampSecs, pub mtime: TimestampSecs,
pub usn: Usn, pub usn: Usn,
pub tags: Vec<String>, pub tags: Vec<String>,
@ -52,7 +52,7 @@ pub struct Note {
/// Tags are stored in their DB form, separated by spaces. /// Tags are stored in their DB form, separated by spaces.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub(crate) struct NoteTags { pub(crate) struct NoteTags {
pub id: NoteID, pub id: NoteId,
pub mtime: TimestampSecs, pub mtime: TimestampSecs,
pub usn: Usn, pub usn: Usn,
pub tags: String, pub tags: String,
@ -68,7 +68,7 @@ impl NoteTags {
impl Note { impl Note {
pub(crate) fn new(notetype: &NoteType) -> Self { pub(crate) fn new(notetype: &NoteType) -> Self {
Note { Note {
id: NoteID(0), id: NoteId(0),
guid: guid(), guid: guid(),
notetype_id: notetype.id, notetype_id: notetype.id,
mtime: TimestampSecs(0), mtime: TimestampSecs(0),
@ -82,9 +82,9 @@ impl Note {
#[allow(clippy::clippy::too_many_arguments)] #[allow(clippy::clippy::too_many_arguments)]
pub(crate) fn new_from_storage( pub(crate) fn new_from_storage(
id: NoteID, id: NoteId,
guid: String, guid: String,
notetype_id: NoteTypeID, notetype_id: NoteTypeId,
mtime: TimestampSecs, mtime: TimestampSecs,
usn: Usn, usn: Usn,
tags: Vec<String>, tags: Vec<String>,
@ -241,9 +241,9 @@ impl From<Note> for pb::Note {
impl From<pb::Note> for Note { impl From<pb::Note> for Note {
fn from(n: pb::Note) -> Self { fn from(n: pb::Note) -> Self {
Note { Note {
id: NoteID(n.id), id: NoteId(n.id),
guid: n.guid, guid: n.guid,
notetype_id: NoteTypeID(n.notetype_id), notetype_id: NoteTypeId(n.notetype_id),
mtime: TimestampSecs(n.mtime_secs as i64), mtime: TimestampSecs(n.mtime_secs as i64),
usn: Usn(n.usn), usn: Usn(n.usn),
tags: n.tags, tags: n.tags,
@ -291,7 +291,7 @@ impl Collection {
Ok(()) Ok(())
} }
pub fn add_note(&mut self, note: &mut Note, did: DeckID) -> Result<OpOutput<()>> { pub fn add_note(&mut self, note: &mut Note, did: DeckId) -> Result<OpOutput<()>> {
self.transact(Op::AddNote, |col| { self.transact(Op::AddNote, |col| {
let nt = col let nt = col
.get_notetype(note.notetype_id)? .get_notetype(note.notetype_id)?
@ -306,7 +306,7 @@ impl Collection {
&mut self, &mut self,
ctx: &CardGenContext, ctx: &CardGenContext,
note: &mut Note, note: &mut Note,
did: DeckID, did: DeckId,
normalize_text: bool, normalize_text: bool,
) -> Result<()> { ) -> Result<()> {
self.canonify_note_tags(note, ctx.usn)?; self.canonify_note_tags(note, ctx.usn)?;
@ -402,7 +402,7 @@ impl Collection {
} }
/// Remove provided notes, and any cards that use them. /// Remove provided notes, and any cards that use them.
pub(crate) fn remove_notes(&mut self, nids: &[NoteID]) -> Result<OpOutput<()>> { pub(crate) fn remove_notes(&mut self, nids: &[NoteId]) -> Result<OpOutput<()>> {
let usn = self.usn()?; let usn = self.usn()?;
self.transact(Op::RemoveNote, |col| { self.transact(Op::RemoveNote, |col| {
for nid in nids { for nid in nids {
@ -422,7 +422,7 @@ impl Collection {
/// If gencards is false, skip card generation. /// If gencards is false, skip card generation.
pub fn after_note_updates( pub fn after_note_updates(
&mut self, &mut self,
nids: &[NoteID], nids: &[NoteId],
generate_cards: bool, generate_cards: bool,
mark_notes_modified: bool, mark_notes_modified: bool,
) -> Result<OpOutput<()>> { ) -> Result<OpOutput<()>> {
@ -440,7 +440,7 @@ impl Collection {
pub(crate) fn transform_notes<F>( pub(crate) fn transform_notes<F>(
&mut self, &mut self,
nids: &[NoteID], nids: &[NoteId],
mut transformer: F, mut transformer: F,
) -> Result<usize> ) -> Result<usize>
where where
@ -528,7 +528,7 @@ impl Collection {
/// Fixme: this currently pulls in the note type, and does more work than necessary. We /// Fixme: this currently pulls in the note type, and does more work than necessary. We
/// could add a separate method to the storage layer to just update the tags in the future, /// could add a separate method to the storage layer to just update the tags in the future,
/// though it does slightly complicate the undo story. /// though it does slightly complicate the undo story.
pub(crate) fn update_note_tags<F>(&mut self, nid: NoteID, mutator: F) -> Result<()> pub(crate) fn update_note_tags<F>(&mut self, nid: NoteId, mutator: F) -> Result<()>
where where
F: Fn(&mut Vec<String>), F: Fn(&mut Vec<String>),
{ {
@ -570,7 +570,7 @@ fn note_differs_from_db(existing_note: &mut Note, note: &mut Note) -> bool {
mod test { mod test {
use super::{anki_base91, field_checksum}; use super::{anki_base91, field_checksum};
use crate::{ use crate::{
collection::open_test_collection, config::BoolKey, decks::DeckID, err::Result, prelude::*, collection::open_test_collection, config::BoolKey, decks::DeckId, err::Result, prelude::*,
search::SortMode, search::SortMode,
}; };
@ -598,7 +598,7 @@ mod test {
let mut note = nt.new_note(); let mut note = nt.new_note();
// if no cards are generated, 1 card is added // if no cards are generated, 1 card is added
col.add_note(&mut note, DeckID(1)).unwrap(); col.add_note(&mut note, DeckId(1)).unwrap();
let existing = col.storage.existing_cards_for_note(note.id)?; let existing = col.storage.existing_cards_for_note(note.id)?;
assert_eq!(existing.len(), 1); assert_eq!(existing.len(), 1);
assert_eq!(existing[0].ord, 0); assert_eq!(existing[0].ord, 0);
@ -620,11 +620,11 @@ mod test {
// cloze cards also generate card 0 if no clozes are found // cloze cards also generate card 0 if no clozes are found
let nt = col.get_notetype_by_name("cloze")?.unwrap(); let nt = col.get_notetype_by_name("cloze")?.unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
col.add_note(&mut note, DeckID(1)).unwrap(); col.add_note(&mut note, DeckId(1)).unwrap();
let existing = col.storage.existing_cards_for_note(note.id)?; let existing = col.storage.existing_cards_for_note(note.id)?;
assert_eq!(existing.len(), 1); assert_eq!(existing.len(), 1);
assert_eq!(existing[0].ord, 0); assert_eq!(existing[0].ord, 0);
assert_eq!(existing[0].original_deck_id, DeckID(1)); assert_eq!(existing[0].original_deck_id, DeckId(1));
// and generate cards for any cloze deletions // and generate cards for any cloze deletions
note.fields[0] = "{{c1::foo}} {{c2::bar}} {{c3::baz}} {{c0::quux}} {{c501::over}}".into(); note.fields[0] = "{{c1::foo}} {{c2::bar}} {{c3::baz}} {{c0::quux}} {{c501::over}}".into();
@ -644,7 +644,7 @@ mod test {
let nt = col.get_notetype_by_name("Basic")?.unwrap(); let nt = col.get_notetype_by_name("Basic")?.unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
note.fields[0] = "\u{fa47}".into(); note.fields[0] = "\u{fa47}".into();
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
assert_eq!(note.fields[0], "\u{6f22}"); assert_eq!(note.fields[0], "\u{6f22}");
// non-normalized searches should be converted // non-normalized searches should be converted
assert_eq!(col.search_cards("\u{fa47}", SortMode::NoOrder)?.len(), 1); assert_eq!(col.search_cards("\u{fa47}", SortMode::NoOrder)?.len(), 1);
@ -659,7 +659,7 @@ mod test {
let mut note = nt.new_note(); let mut note = nt.new_note();
note.fields[0] = "\u{fa47}".into(); note.fields[0] = "\u{fa47}".into();
col.set_config(BoolKey::NormalizeNoteText, &false).unwrap(); col.set_config(BoolKey::NormalizeNoteText, &false).unwrap();
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
assert_eq!(note.fields[0], "\u{fa47}"); assert_eq!(note.fields[0], "\u{fa47}");
// normalized searches won't match // normalized searches won't match
assert_eq!(col.search_cards("\u{6f22}", SortMode::NoOrder)?.len(), 0); assert_eq!(col.search_cards("\u{6f22}", SortMode::NoOrder)?.len(), 0);
@ -704,7 +704,7 @@ mod test {
note.set_field(0, "a")?; note.set_field(0, "a")?;
note.set_field(1, "b")?; note.set_field(1, "b")?;
col.add_note(&mut note, DeckID(1)).unwrap(); col.add_note(&mut note, DeckId(1)).unwrap();
assert_after_add(&mut col)?; assert_after_add(&mut col)?;
col.undo()?; col.undo()?;

View File

@ -10,8 +10,8 @@ pub(crate) enum UndoableNoteChange {
Added(Box<Note>), Added(Box<Note>),
Updated(Box<Note>), Updated(Box<Note>),
Removed(Box<Note>), Removed(Box<Note>),
GraveAdded(Box<(NoteID, Usn)>), GraveAdded(Box<(NoteId, Usn)>),
GraveRemoved(Box<(NoteID, Usn)>), GraveRemoved(Box<(NoteId, Usn)>),
TagsUpdated(Box<NoteTags>), TagsUpdated(Box<NoteTags>),
} }
@ -49,7 +49,7 @@ impl Collection {
} }
/// Remove a note. Cards must already have been deleted. /// Remove a note. Cards must already have been deleted.
pub(crate) fn remove_note_only_undoable(&mut self, nid: NoteID, usn: Usn) -> Result<()> { pub(crate) fn remove_note_only_undoable(&mut self, nid: NoteId, usn: Usn) -> Result<()> {
if let Some(note) = self.storage.get_note(nid)? { if let Some(note) = self.storage.get_note(nid)? {
self.save_undo(UndoableNoteChange::Removed(Box::new(note))); self.save_undo(UndoableNoteChange::Removed(Box::new(note)));
self.storage.remove_note(nid)?; self.storage.remove_note(nid)?;
@ -112,12 +112,12 @@ impl Collection {
Ok(()) Ok(())
} }
fn add_note_grave(&mut self, nid: NoteID, usn: Usn) -> Result<()> { fn add_note_grave(&mut self, nid: NoteId, usn: Usn) -> Result<()> {
self.save_undo(UndoableNoteChange::GraveAdded(Box::new((nid, usn)))); self.save_undo(UndoableNoteChange::GraveAdded(Box::new((nid, usn))));
self.storage.add_note_grave(nid, usn) self.storage.add_note_grave(nid, usn)
} }
fn remove_note_grave(&mut self, nid: NoteID, usn: Usn) -> Result<()> { fn remove_note_grave(&mut self, nid: NoteId, usn: Usn) -> Result<()> {
self.save_undo(UndoableNoteChange::GraveRemoved(Box::new((nid, usn)))); self.save_undo(UndoableNoteChange::GraveRemoved(Box::new((nid, usn))));
self.storage.remove_note_grave(nid) self.storage.remove_note_grave(nid)
} }

View File

@ -3,13 +3,13 @@
use super::NoteType; use super::NoteType;
use crate::{ use crate::{
card::{Card, CardID}, card::{Card, CardId},
cloze::add_cloze_numbers_in_string, cloze::add_cloze_numbers_in_string,
collection::Collection, collection::Collection,
deckconf::{DeckConf, DeckConfID}, deckconf::{DeckConf, DeckConfId},
decks::DeckID, decks::DeckId,
err::{AnkiError, Result}, err::{AnkiError, Result},
notes::{Note, NoteID}, notes::{Note, NoteId},
notetype::NoteTypeKind, notetype::NoteTypeKind,
template::ParsedTemplate, template::ParsedTemplate,
types::Usn, types::Usn,
@ -21,17 +21,17 @@ use std::collections::{HashMap, HashSet};
/// Info about an existing card required when generating new cards /// Info about an existing card required when generating new cards
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub(crate) struct AlreadyGeneratedCardInfo { pub(crate) struct AlreadyGeneratedCardInfo {
pub id: CardID, pub id: CardId,
pub nid: NoteID, pub nid: NoteId,
pub ord: u32, pub ord: u32,
pub original_deck_id: DeckID, pub original_deck_id: DeckId,
pub position_if_new: Option<u32>, pub position_if_new: Option<u32>,
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct CardToGenerate { pub(crate) struct CardToGenerate {
pub ord: u32, pub ord: u32,
pub did: Option<DeckID>, pub did: Option<DeckId>,
pub due: Option<u32>, pub due: Option<u32>,
} }
@ -39,7 +39,7 @@ pub(crate) struct CardToGenerate {
/// and which deck it should be placed in. /// and which deck it should be placed in.
pub(crate) struct SingleCardGenContext { pub(crate) struct SingleCardGenContext {
template: Option<ParsedTemplate>, template: Option<ParsedTemplate>,
target_deck_id: Option<DeckID>, target_deck_id: Option<DeckId>,
} }
/// Info required to determine which cards should be generated when note added/updated, /// Info required to determine which cards should be generated when note added/updated,
@ -54,7 +54,7 @@ pub(crate) struct CardGenContext<'a> {
#[derive(Default)] #[derive(Default)]
pub(crate) struct CardGenCache { pub(crate) struct CardGenCache {
next_position: Option<u32>, next_position: Option<u32>,
deck_configs: HashMap<DeckID, DeckConf>, deck_configs: HashMap<DeckId, DeckConf>,
} }
impl CardGenContext<'_> { impl CardGenContext<'_> {
@ -169,7 +169,7 @@ impl CardGenContext<'_> {
// this could be reworked in the future to avoid the extra vec allocation // this could be reworked in the future to avoid the extra vec allocation
pub(super) fn group_generated_cards_by_note( pub(super) fn group_generated_cards_by_note(
items: Vec<AlreadyGeneratedCardInfo>, items: Vec<AlreadyGeneratedCardInfo>,
) -> Vec<(NoteID, Vec<AlreadyGeneratedCardInfo>)> { ) -> Vec<(NoteId, Vec<AlreadyGeneratedCardInfo>)> {
let mut out = vec![]; let mut out = vec![];
for (key, group) in &items.into_iter().group_by(|c| c.nid) { for (key, group) in &items.into_iter().group_by(|c| c.nid) {
out.push((key, group.collect())); out.push((key, group.collect()));
@ -182,7 +182,7 @@ pub(crate) struct ExtractedCardInfo {
// if set, the due position new cards should be given // if set, the due position new cards should be given
pub due: Option<u32>, pub due: Option<u32>,
// if set, the deck all current cards are in // if set, the deck all current cards are in
pub deck_id: Option<DeckID>, pub deck_id: Option<DeckId>,
pub existing_ords: HashSet<u32>, pub existing_ords: HashSet<u32>,
} }
@ -214,7 +214,7 @@ impl Collection {
&mut self, &mut self,
ctx: &CardGenContext, ctx: &CardGenContext,
note: &Note, note: &Note,
target_deck_id: DeckID, target_deck_id: DeckId,
) -> Result<()> { ) -> Result<()> {
self.generate_cards_for_note( self.generate_cards_for_note(
ctx, ctx,
@ -245,7 +245,7 @@ impl Collection {
ctx: &CardGenContext, ctx: &CardGenContext,
note: &Note, note: &Note,
existing: &[AlreadyGeneratedCardInfo], existing: &[AlreadyGeneratedCardInfo],
target_deck_id: Option<DeckID>, target_deck_id: Option<DeckId>,
cache: &mut CardGenCache, cache: &mut CardGenCache,
) -> Result<()> { ) -> Result<()> {
let cards = ctx.new_cards_required(note, &existing, true); let cards = ctx.new_cards_required(note, &existing, true);
@ -277,9 +277,9 @@ impl Collection {
pub(crate) fn add_generated_cards( pub(crate) fn add_generated_cards(
&mut self, &mut self,
nid: NoteID, nid: NoteId,
cards: &[CardToGenerate], cards: &[CardToGenerate],
target_deck_id: Option<DeckID>, target_deck_id: Option<DeckId>,
cache: &mut CardGenCache, cache: &mut CardGenCache,
) -> Result<()> { ) -> Result<()> {
for c in cards { for c in cards {
@ -301,8 +301,8 @@ impl Collection {
#[allow(clippy::map_entry)] #[allow(clippy::map_entry)]
fn due_for_deck( fn due_for_deck(
&mut self, &mut self,
did: DeckID, did: DeckId,
dcid: DeckConfID, dcid: DeckConfId,
cache: &mut CardGenCache, cache: &mut CardGenCache,
) -> Result<u32> { ) -> Result<u32> {
if !cache.deck_configs.contains_key(&did) { if !cache.deck_configs.contains_key(&did) {
@ -322,7 +322,7 @@ impl Collection {
} }
/// If deck ID does not exist or points to a filtered deck, fall back on default. /// If deck ID does not exist or points to a filtered deck, fall back on default.
fn deck_for_adding(&mut self, did: Option<DeckID>) -> Result<(DeckID, DeckConfID)> { fn deck_for_adding(&mut self, did: Option<DeckId>) -> Result<(DeckId, DeckConfId)> {
if let Some(did) = did { if let Some(did) = did {
if let Some(deck) = self.deck_conf_if_normal(did)? { if let Some(deck) = self.deck_conf_if_normal(did)? {
return Ok(deck); return Ok(deck);
@ -332,15 +332,15 @@ impl Collection {
self.default_deck_conf() self.default_deck_conf()
} }
fn default_deck_conf(&mut self) -> Result<(DeckID, DeckConfID)> { fn default_deck_conf(&mut self) -> Result<(DeckId, DeckConfId)> {
// currently hard-coded to 1, we could create this as needed in the future // currently hard-coded to 1, we could create this as needed in the future
Ok(self Ok(self
.deck_conf_if_normal(DeckID(1))? .deck_conf_if_normal(DeckId(1))?
.ok_or_else(|| AnkiError::invalid_input("invalid default deck"))?) .ok_or_else(|| AnkiError::invalid_input("invalid default deck"))?)
} }
/// If deck exists and and is a normal deck, return its ID and config /// If deck exists and and is a normal deck, return its ID and config
fn deck_conf_if_normal(&mut self, did: DeckID) -> Result<Option<(DeckID, DeckConfID)>> { fn deck_conf_if_normal(&mut self, did: DeckId) -> Result<Option<(DeckId, DeckConfId)>> {
Ok(self.get_deck(did)?.and_then(|d| { Ok(self.get_deck(did)?.and_then(|d| {
if let Some(conf_id) = d.config_id() { if let Some(conf_id) = d.config_id() {
Some((did, conf_id)) Some((did, conf_id))

View File

@ -2,16 +2,16 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use super::{ use super::{
cardgen::group_generated_cards_by_note, CardGenContext, NoteType, NoteTypeID, NoteTypeKind, cardgen::group_generated_cards_by_note, CardGenContext, NoteType, NoteTypeId, NoteTypeKind,
}; };
use crate::{card::CardID, collection::Collection, err::Result, notes::NoteID}; use crate::{card::CardId, collection::Collection, err::Result, notes::NoteId};
use std::collections::HashSet; use std::collections::HashSet;
use std::fmt::Write; use std::fmt::Write;
pub struct EmptyCardsForNote { pub struct EmptyCardsForNote {
pub nid: NoteID, pub nid: NoteId,
// (ordinal, card id) // (ordinal, card id)
pub empty: Vec<(u32, CardID)>, pub empty: Vec<(u32, CardId)>,
pub current_count: usize, pub current_count: usize,
} }
@ -49,7 +49,7 @@ impl Collection {
Ok(out) Ok(out)
} }
pub fn empty_cards(&mut self) -> Result<Vec<(NoteTypeID, Vec<EmptyCardsForNote>)>> { pub fn empty_cards(&mut self) -> Result<Vec<(NoteTypeId, Vec<EmptyCardsForNote>)>> {
self.storage self.storage
.get_all_notetype_names()? .get_all_notetype_names()?
.into_iter() .into_iter()
@ -63,7 +63,7 @@ impl Collection {
/// Create a report on empty cards. Mutates the provided data to sort ordinals. /// Create a report on empty cards. Mutates the provided data to sort ordinals.
pub fn empty_cards_report( pub fn empty_cards_report(
&mut self, &mut self,
empty: &mut [(NoteTypeID, Vec<EmptyCardsForNote>)], empty: &mut [(NoteTypeId, Vec<EmptyCardsForNote>)],
) -> Result<String> { ) -> Result<String> {
let nts = self.get_all_notetypes()?; let nts = self.get_all_notetypes()?;
let mut buf = String::new(); let mut buf = String::new();

View File

@ -24,7 +24,7 @@ pub use templates::CardTemplate;
use crate::{ use crate::{
collection::Collection, collection::Collection,
decks::DeckID, decks::DeckId,
define_newtype, define_newtype,
err::{AnkiError, Result}, err::{AnkiError, Result},
notes::Note, notes::Note,
@ -40,7 +40,7 @@ use std::{
}; };
use unicase::UniCase; use unicase::UniCase;
define_newtype!(NoteTypeID, i64); define_newtype!(NoteTypeId, i64);
pub(crate) const DEFAULT_CSS: &str = include_str!("styling.css"); pub(crate) const DEFAULT_CSS: &str = include_str!("styling.css");
pub(crate) const DEFAULT_LATEX_HEADER: &str = include_str!("header.tex"); pub(crate) const DEFAULT_LATEX_HEADER: &str = include_str!("header.tex");
@ -48,7 +48,7 @@ pub(crate) const DEFAULT_LATEX_FOOTER: &str = r"\end{document}";
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct NoteType { pub struct NoteType {
pub id: NoteTypeID, pub id: NoteTypeId,
pub name: String, pub name: String,
pub mtime_secs: TimestampSecs, pub mtime_secs: TimestampSecs,
pub usn: Usn, pub usn: Usn,
@ -60,7 +60,7 @@ pub struct NoteType {
impl Default for NoteType { impl Default for NoteType {
fn default() -> Self { fn default() -> Self {
NoteType { NoteType {
id: NoteTypeID(0), id: NoteTypeId(0),
name: "".into(), name: "".into(),
mtime_secs: TimestampSecs(0), mtime_secs: TimestampSecs(0),
usn: Usn(0), usn: Usn(0),
@ -324,8 +324,8 @@ impl NoteType {
Note::new(&self) Note::new(&self)
} }
pub fn target_deck_id(&self) -> DeckID { pub fn target_deck_id(&self) -> DeckId {
DeckID(self.config.target_deck_id) DeckId(self.config.target_deck_id)
} }
fn fix_field_names(&mut self) -> Result<()> { fn fix_field_names(&mut self) -> Result<()> {
@ -455,7 +455,7 @@ impl Collection {
} }
} }
pub fn get_notetype(&mut self, ntid: NoteTypeID) -> Result<Option<Arc<NoteType>>> { pub fn get_notetype(&mut self, ntid: NoteTypeId) -> Result<Option<Arc<NoteType>>> {
if let Some(nt) = self.state.notetype_cache.get(&ntid) { if let Some(nt) = self.state.notetype_cache.get(&ntid) {
return Ok(Some(nt.clone())); return Ok(Some(nt.clone()));
} }
@ -468,7 +468,7 @@ impl Collection {
} }
} }
pub fn get_all_notetypes(&mut self) -> Result<HashMap<NoteTypeID, Arc<NoteType>>> { pub fn get_all_notetypes(&mut self) -> Result<HashMap<NoteTypeId, Arc<NoteType>>> {
self.storage self.storage
.get_all_notetype_names()? .get_all_notetype_names()?
.into_iter() .into_iter()
@ -481,7 +481,7 @@ impl Collection {
.collect() .collect()
} }
pub fn remove_notetype(&mut self, ntid: NoteTypeID) -> Result<()> { pub fn remove_notetype(&mut self, ntid: NoteTypeId) -> Result<()> {
// fixme: currently the storage layer is taking care of removing the notes and cards, // fixme: currently the storage layer is taking care of removing the notes and cards,
// but we need to do it in this layer in the future for undo handling // but we need to do it in this layer in the future for undo handling
self.transact_no_undo(|col| { self.transact_no_undo(|col| {

View File

@ -3,11 +3,11 @@
use super::{CardTemplate, NoteType, NoteTypeKind}; use super::{CardTemplate, NoteType, NoteTypeKind};
use crate::{ use crate::{
card::{Card, CardID}, card::{Card, CardId},
collection::Collection, collection::Collection,
err::{AnkiError, Result}, err::{AnkiError, Result},
i18n::I18n, i18n::I18n,
notes::{Note, NoteID}, notes::{Note, NoteId},
template::{field_is_empty, render_card, ParsedTemplate, RenderedNode}, template::{field_is_empty, render_card, ParsedTemplate, RenderedNode},
}; };
use std::{borrow::Cow, collections::HashMap}; use std::{borrow::Cow, collections::HashMap};
@ -19,7 +19,7 @@ pub struct RenderCardOutput {
impl Collection { impl Collection {
/// Render an existing card saved in the database. /// Render an existing card saved in the database.
pub fn render_existing_card(&mut self, cid: CardID, browser: bool) -> Result<RenderCardOutput> { pub fn render_existing_card(&mut self, cid: CardId, browser: bool) -> Result<RenderCardOutput> {
let card = self let card = self
.storage .storage
.get_card(cid)? .get_card(cid)?
@ -64,7 +64,7 @@ impl Collection {
fn existing_or_synthesized_card( fn existing_or_synthesized_card(
&self, &self,
nid: NoteID, nid: NoteId,
template_ord: Option<u32>, template_ord: Option<u32>,
card_ord: u16, card_ord: u16,
) -> Result<Card> { ) -> Result<Card> {

View File

@ -2,7 +2,7 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{ use crate::{
decks::DeckID, decks::DeckId,
notetype::{ notetype::{
CardRequirement, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, NoteType, CardRequirement, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, NoteType,
NoteTypeConfig, NoteTypeConfig,
@ -17,7 +17,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
use serde_tuple::Serialize_tuple; use serde_tuple::Serialize_tuple;
use std::collections::HashMap; use std::collections::HashMap;
use super::{CardRequirementKind, NoteTypeID}; use super::{CardRequirementKind, NoteTypeId};
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone)] #[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone)]
#[repr(u8)] #[repr(u8)]
@ -30,7 +30,7 @@ pub enum NoteTypeKind {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct NoteTypeSchema11 { pub struct NoteTypeSchema11 {
#[serde(deserialize_with = "deserialize_number_from_string")] #[serde(deserialize_with = "deserialize_number_from_string")]
pub(crate) id: NoteTypeID, pub(crate) id: NoteTypeId,
pub(crate) name: String, pub(crate) name: String,
#[serde(rename = "type")] #[serde(rename = "type")]
pub(crate) kind: NoteTypeKind, pub(crate) kind: NoteTypeKind,
@ -39,7 +39,7 @@ pub struct NoteTypeSchema11 {
pub(crate) usn: Usn, pub(crate) usn: Usn,
pub(crate) sortf: u16, pub(crate) sortf: u16,
#[serde(deserialize_with = "default_on_invalid")] #[serde(deserialize_with = "default_on_invalid")]
pub(crate) did: Option<DeckID>, pub(crate) did: Option<DeckId>,
pub(crate) tmpls: Vec<CardTemplateSchema11>, pub(crate) tmpls: Vec<CardTemplateSchema11>,
pub(crate) flds: Vec<NoteFieldSchema11>, pub(crate) flds: Vec<NoteFieldSchema11>,
#[serde(deserialize_with = "default_on_invalid")] #[serde(deserialize_with = "default_on_invalid")]
@ -97,7 +97,7 @@ impl From<NoteTypeSchema11> for NoteType {
kind: nt.kind as i32, kind: nt.kind as i32,
sort_field_idx: nt.sortf as u32, sort_field_idx: nt.sortf as u32,
css: nt.css, css: nt.css,
target_deck_id: nt.did.unwrap_or(DeckID(0)).0, target_deck_id: nt.did.unwrap_or(DeckId(0)).0,
latex_pre: nt.latex_pre, latex_pre: nt.latex_pre,
latex_post: nt.latex_post, latex_post: nt.latex_post,
latex_svg: nt.latexsvg, latex_svg: nt.latexsvg,
@ -150,7 +150,7 @@ impl From<NoteType> for NoteTypeSchema11 {
did: if c.target_deck_id == 0 { did: if c.target_deck_id == 0 {
None None
} else { } else {
Some(DeckID(c.target_deck_id)) Some(DeckId(c.target_deck_id))
}, },
tmpls: p.templates.into_iter().map(Into::into).collect(), tmpls: p.templates.into_iter().map(Into::into).collect(),
flds: p.fields.into_iter().map(Into::into).collect(), flds: p.fields.into_iter().map(Into::into).collect(),
@ -265,7 +265,7 @@ pub struct CardTemplateSchema11 {
#[serde(default)] #[serde(default)]
pub(crate) bafmt: String, pub(crate) bafmt: String,
#[serde(deserialize_with = "default_on_invalid", default)] #[serde(deserialize_with = "default_on_invalid", default)]
pub(crate) did: Option<DeckID>, pub(crate) did: Option<DeckId>,
#[serde(default, deserialize_with = "default_on_invalid")] #[serde(default, deserialize_with = "default_on_invalid")]
pub(crate) bfont: String, pub(crate) bfont: String,
#[serde(default, deserialize_with = "default_on_invalid")] #[serde(default, deserialize_with = "default_on_invalid")]
@ -286,7 +286,7 @@ impl From<CardTemplateSchema11> for CardTemplate {
a_format: t.afmt, a_format: t.afmt,
q_format_browser: t.bqfmt, q_format_browser: t.bqfmt,
a_format_browser: t.bafmt, a_format_browser: t.bafmt,
target_deck_id: t.did.unwrap_or(DeckID(0)).0, target_deck_id: t.did.unwrap_or(DeckId(0)).0,
browser_font_name: t.bfont, browser_font_name: t.bfont,
browser_font_size: t.bsize as u32, browser_font_size: t.bsize as u32,
other: other_to_bytes(&t.other), other: other_to_bytes(&t.other),
@ -308,7 +308,7 @@ impl From<CardTemplate> for CardTemplateSchema11 {
bqfmt: conf.q_format_browser, bqfmt: conf.q_format_browser,
bafmt: conf.a_format_browser, bafmt: conf.a_format_browser,
did: if conf.target_deck_id > 0 { did: if conf.target_deck_id > 0 {
Some(DeckID(conf.target_deck_id)) Some(DeckId(conf.target_deck_id))
} else { } else {
None None
}, },

View File

@ -137,7 +137,7 @@ impl Collection {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{ords_changed, TemplateOrdChanges}; use super::{ords_changed, TemplateOrdChanges};
use crate::{collection::open_test_collection, decks::DeckID, err::Result, search::SortMode}; use crate::{collection::open_test_collection, decks::DeckId, err::Result, search::SortMode};
#[test] #[test]
fn ord_changes() { fn ord_changes() {
@ -205,7 +205,7 @@ mod test {
assert_eq!(note.fields().len(), 2); assert_eq!(note.fields().len(), 2);
note.set_field(0, "one")?; note.set_field(0, "one")?;
note.set_field(1, "two")?; note.set_field(1, "two")?;
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
nt.add_field("three"); nt.add_field("three");
col.update_notetype(&mut nt, false)?; col.update_notetype(&mut nt, false)?;
@ -254,7 +254,7 @@ mod test {
assert_eq!(note.fields().len(), 2); assert_eq!(note.fields().len(), 2);
note.set_field(0, "one")?; note.set_field(0, "one")?;
note.set_field(1, "two")?; note.set_field(1, "two")?;
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
assert_eq!( assert_eq!(
col.search_cards(&format!("nid:{}", note.id), SortMode::NoOrder) col.search_cards(&format!("nid:{}", note.id), SortMode::NoOrder)

View File

@ -19,7 +19,7 @@ impl SqliteStorage {
self.add_new_notetype(&mut nt)?; self.add_new_notetype(&mut nt)?;
if idx == Kind::Basic as usize { if idx == Kind::Basic as usize {
self.set_config_entry(&ConfigEntry::boxed( self.set_config_entry(&ConfigEntry::boxed(
ConfigKey::CurrentNoteTypeID.into(), ConfigKey::CurrentNoteTypeId.into(),
serde_json::to_vec(&nt.id)?, serde_json::to_vec(&nt.id)?,
self.usn(false)?, self.usn(false)?,
TimestampSecs::now(), TimestampSecs::now(),

View File

@ -3,7 +3,7 @@
use crate::{ use crate::{
backend_proto::{CardTemplate as CardTemplateProto, CardTemplateConfig, OptionalUInt32}, backend_proto::{CardTemplate as CardTemplateProto, CardTemplateConfig, OptionalUInt32},
decks::DeckID, decks::DeckId,
err::{AnkiError, Result}, err::{AnkiError, Result},
template::ParsedTemplate, template::ParsedTemplate,
timestamp::TimestampSecs, timestamp::TimestampSecs,
@ -44,9 +44,9 @@ impl CardTemplate {
} }
} }
pub(crate) fn target_deck_id(&self) -> Option<DeckID> { pub(crate) fn target_deck_id(&self) -> Option<DeckId> {
if self.config.target_deck_id > 0 { if self.config.target_deck_id > 0 {
Some(DeckID(self.config.target_deck_id)) Some(DeckId(self.config.target_deck_id))
} else { } else {
None None
} }

View File

@ -2,17 +2,17 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
pub use crate::{ pub use crate::{
card::{Card, CardID}, card::{Card, CardId},
collection::Collection, collection::Collection,
config::BoolKey, config::BoolKey,
deckconf::{DeckConf, DeckConfID}, deckconf::{DeckConf, DeckConfId},
decks::{Deck, DeckID, DeckKind}, decks::{Deck, DeckId, DeckKind},
err::{AnkiError, Result}, err::{AnkiError, Result},
i18n::I18n, i18n::I18n,
notes::{Note, NoteID}, notes::{Note, NoteId},
notetype::{NoteType, NoteTypeID}, notetype::{NoteType, NoteTypeId},
ops::{Op, OpChanges, OpOutput}, ops::{Op, OpChanges, OpOutput},
revlog::RevlogID, revlog::RevlogId,
timestamp::{TimestampMillis, TimestampSecs}, timestamp::{TimestampMillis, TimestampSecs},
types::Usn, types::Usn,
}; };

View File

@ -10,11 +10,11 @@ use serde::Deserialize;
use serde_repr::{Deserialize_repr, Serialize_repr}; use serde_repr::{Deserialize_repr, Serialize_repr};
use serde_tuple::Serialize_tuple; use serde_tuple::Serialize_tuple;
define_newtype!(RevlogID, i64); define_newtype!(RevlogId, i64);
impl RevlogID { impl RevlogId {
pub fn new() -> Self { pub fn new() -> Self {
RevlogID(TimestampMillis::now().0) RevlogId(TimestampMillis::now().0)
} }
pub fn as_secs(self) -> TimestampSecs { pub fn as_secs(self) -> TimestampSecs {
@ -22,16 +22,16 @@ impl RevlogID {
} }
} }
impl From<TimestampMillis> for RevlogID { impl From<TimestampMillis> for RevlogId {
fn from(m: TimestampMillis) -> Self { fn from(m: TimestampMillis) -> Self {
RevlogID(m.0) RevlogId(m.0)
} }
} }
#[derive(Serialize_tuple, Deserialize, Debug, Default, PartialEq)] #[derive(Serialize_tuple, Deserialize, Debug, Default, PartialEq)]
pub struct RevlogEntry { pub struct RevlogEntry {
pub id: RevlogID, pub id: RevlogId,
pub cid: CardID, pub cid: CardId,
pub usn: Usn, pub usn: Usn,
/// - In the V1 scheduler, 3 represents easy in the learning case. /// - In the V1 scheduler, 3 represents easy in the learning case.
/// - 0 represents manual rescheduling. /// - 0 represents manual rescheduling.
@ -88,7 +88,7 @@ impl Collection {
usn: Usn, usn: Usn,
) -> Result<()> { ) -> Result<()> {
let entry = RevlogEntry { let entry = RevlogEntry {
id: RevlogID::new(), id: RevlogId::new(),
cid: card.id, cid: card.id,
usn, usn,
button_chosen: 0, button_chosen: 0,

View File

@ -27,7 +27,7 @@ impl Collection {
} }
/// Add the provided revlog entry, modifying the ID if it is not unique. /// Add the provided revlog entry, modifying the ID if it is not unique.
pub(crate) fn add_revlog_entry_undoable(&mut self, mut entry: RevlogEntry) -> Result<RevlogID> { pub(crate) fn add_revlog_entry_undoable(&mut self, mut entry: RevlogEntry) -> Result<RevlogId> {
entry.id = self.storage.add_revlog_entry(&entry, true)?; entry.id = self.storage.add_revlog_entry(&entry, true)?;
let id = entry.id; let id = entry.id;
self.save_undo(UndoableRevlogChange::Added(Box::new(entry))); self.save_undo(UndoableRevlogChange::Added(Box::new(entry)));

View File

@ -36,7 +36,7 @@ pub enum Rating {
} }
pub struct CardAnswer { pub struct CardAnswer {
pub card_id: CardID, pub card_id: CardId,
pub current_state: CardState, pub current_state: CardState,
pub new_state: CardState, pub new_state: CardState,
pub rating: Rating, pub rating: Rating,
@ -184,7 +184,7 @@ impl Rating {
impl Collection { impl Collection {
/// Return the next states that will be applied for each answer button. /// Return the next states that will be applied for each answer button.
pub fn get_next_card_states(&mut self, cid: CardID) -> Result<NextCardStates> { pub fn get_next_card_states(&mut self, cid: CardId) -> Result<NextCardStates> {
let card = self.storage.get_card(cid)?.ok_or(AnkiError::NotFound)?; let card = self.storage.get_card(cid)?.ok_or(AnkiError::NotFound)?;
let ctx = self.card_state_updater(card)?; let ctx = self.card_state_updater(card)?;
let current = ctx.current_card_state(); let current = ctx.current_card_state();
@ -355,8 +355,8 @@ impl Collection {
fn home_deck_config( fn home_deck_config(
&self, &self,
config_id: Option<DeckConfID>, config_id: Option<DeckConfId>,
home_deck_id: DeckID, home_deck_id: DeckId,
) -> Result<DeckConf> { ) -> Result<DeckConf> {
let config_id = if let Some(config_id) = config_id { let config_id = if let Some(config_id) = config_id {
config_id config_id
@ -371,7 +371,7 @@ impl Collection {
Ok(self.storage.get_deck_config(config_id)?.unwrap_or_default()) Ok(self.storage.get_deck_config(config_id)?.unwrap_or_default())
} }
fn add_leech_tag(&mut self, nid: NoteID) -> Result<()> { fn add_leech_tag(&mut self, nid: NoteId) -> Result<()> {
self.update_note_tags(nid, |tags| tags.push("leech".into())) self.update_note_tags(nid, |tags| tags.push("leech".into()))
} }
} }

View File

@ -63,7 +63,7 @@ mod test {
fn preview() -> Result<()> { fn preview() -> Result<()> {
let mut col = open_test_collection(); let mut col = open_test_collection();
let mut c = Card { let mut c = Card {
deck_id: DeckID(1), deck_id: DeckId(1),
ctype: CardType::Learn, ctype: CardType::Learn,
queue: CardQueue::DayLearn, queue: CardQueue::DayLearn,
remaining_steps: 2, remaining_steps: 2,

View File

@ -38,7 +38,7 @@ impl RevlogEntryPartial {
pub(super) fn into_revlog_entry( pub(super) fn into_revlog_entry(
self, self,
usn: Usn, usn: Usn,
cid: CardID, cid: CardId,
button_chosen: u8, button_chosen: u8,
answered_at: TimestampMillis, answered_at: TimestampMillis,
taken_millis: u32, taken_millis: u32,

View File

@ -21,10 +21,10 @@ mod test {
let mut note = nt.new_note(); let mut note = nt.new_note();
note.set_field(0, "one")?; note.set_field(0, "one")?;
note.set_field(1, "two")?; note.set_field(1, "two")?;
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
// turn burying and leech suspension on // turn burying and leech suspension on
let mut conf = col.storage.get_deck_config(DeckConfID(1))?.unwrap(); let mut conf = col.storage.get_deck_config(DeckConfId(1))?.unwrap();
conf.inner.bury_new = true; conf.inner.bury_new = true;
conf.inner.leech_action = LeechAction::Suspend as i32; conf.inner.leech_action = LeechAction::Suspend as i32;
col.storage.update_deck_conf(&conf)?; col.storage.update_deck_conf(&conf)?;
@ -94,7 +94,7 @@ mod test {
assert_eq!(note.tags, vec!["leech".to_string()]); assert_eq!(note.tags, vec!["leech".to_string()]);
assert_eq!(col.storage.all_tags()?.is_empty(), false); assert_eq!(col.storage.all_tags()?.is_empty(), false);
let deck = col.get_deck(DeckID(1))?.unwrap(); let deck = col.get_deck(DeckId(1))?.unwrap();
assert_eq!(deck.common.review_studied, 1); assert_eq!(deck.common.review_studied, 1);
dbg!(&col.next_card()?); dbg!(&col.next_card()?);
@ -121,7 +121,7 @@ mod test {
assert_eq!(note.tags.is_empty(), true); assert_eq!(note.tags.is_empty(), true);
assert_eq!(col.storage.all_tags()?.is_empty(), true); assert_eq!(col.storage.all_tags()?.is_empty(), true);
let deck = col.get_deck(DeckID(1))?.unwrap(); let deck = col.get_deck(DeckId(1))?.unwrap();
assert_eq!(deck.common.review_studied, 0); assert_eq!(deck.common.review_studied, 0);
assert_eq!(col.next_card()?.is_some(), true); assert_eq!(col.next_card()?.is_some(), true);

View File

@ -3,7 +3,7 @@
use crate::{ use crate::{
backend_proto as pb, backend_proto as pb,
card::{Card, CardID, CardQueue}, card::{Card, CardId, CardQueue},
collection::Collection, collection::Collection,
config::SchedulerVersion, config::SchedulerVersion,
err::Result, err::Result,
@ -68,7 +68,7 @@ impl Collection {
self.storage.clear_searched_cards_table() self.storage.clear_searched_cards_table()
} }
pub fn unbury_or_unsuspend_cards(&mut self, cids: &[CardID]) -> Result<OpOutput<()>> { pub fn unbury_or_unsuspend_cards(&mut self, cids: &[CardId]) -> Result<OpOutput<()>> {
self.transact(Op::UnburyUnsuspend, |col| { self.transact(Op::UnburyUnsuspend, |col| {
col.storage.set_search_table_to_card_ids(cids, false)?; col.storage.set_search_table_to_card_ids(cids, false)?;
col.unsuspend_or_unbury_searched_cards() col.unsuspend_or_unbury_searched_cards()
@ -122,7 +122,7 @@ impl Collection {
pub fn bury_or_suspend_cards( pub fn bury_or_suspend_cards(
&mut self, &mut self,
cids: &[CardID], cids: &[CardId],
mode: BuryOrSuspendMode, mode: BuryOrSuspendMode,
) -> Result<OpOutput<()>> { ) -> Result<OpOutput<()>> {
let op = match mode { let op = match mode {
@ -137,8 +137,8 @@ impl Collection {
pub(crate) fn bury_siblings( pub(crate) fn bury_siblings(
&mut self, &mut self,
cid: CardID, cid: CardId,
nid: NoteID, nid: NoteId,
include_new: bool, include_new: bool,
include_reviews: bool, include_reviews: bool,
) -> Result<()> { ) -> Result<()> {

View File

@ -72,7 +72,7 @@ impl Card {
} }
} }
pub(crate) fn original_or_current_deck_id(&self) -> DeckID { pub(crate) fn original_or_current_deck_id(&self) -> DeckId {
if self.original_deck_id.0 > 0 { if self.original_deck_id.0 > 0 {
self.original_deck_id self.original_deck_id
} else { } else {

View File

@ -18,13 +18,13 @@ use crate::{
/// Contains the parts of a filtered deck required for modifying its settings in /// Contains the parts of a filtered deck required for modifying its settings in
/// the UI. /// the UI.
pub struct FilteredDeckForUpdate { pub struct FilteredDeckForUpdate {
pub id: DeckID, pub id: DeckId,
pub human_name: String, pub human_name: String,
pub config: FilteredDeck, pub config: FilteredDeck,
} }
pub(crate) struct DeckFilterContext<'a> { pub(crate) struct DeckFilterContext<'a> {
pub target_deck: DeckID, pub target_deck: DeckId,
pub config: &'a FilteredDeck, pub config: &'a FilteredDeck,
pub scheduler: SchedulerVersion, pub scheduler: SchedulerVersion,
pub usn: Usn, pub usn: Usn,
@ -36,7 +36,7 @@ impl Collection {
/// will not be added to the DB. /// will not be added to the DB.
pub fn get_or_create_filtered_deck( pub fn get_or_create_filtered_deck(
&mut self, &mut self,
deck_id: DeckID, deck_id: DeckId,
) -> Result<FilteredDeckForUpdate> { ) -> Result<FilteredDeckForUpdate> {
let deck = if deck_id.0 == 0 { let deck = if deck_id.0 == 0 {
self.new_filtered_deck_for_adding()? self.new_filtered_deck_for_adding()?
@ -55,20 +55,20 @@ impl Collection {
pub fn add_or_update_filtered_deck( pub fn add_or_update_filtered_deck(
&mut self, &mut self,
deck: FilteredDeckForUpdate, deck: FilteredDeckForUpdate,
) -> Result<OpOutput<DeckID>> { ) -> Result<OpOutput<DeckId>> {
self.transact(Op::BuildFilteredDeck, |col| { self.transact(Op::BuildFilteredDeck, |col| {
col.add_or_update_filtered_deck_inner(deck) col.add_or_update_filtered_deck_inner(deck)
}) })
} }
pub fn empty_filtered_deck(&mut self, did: DeckID) -> Result<OpOutput<()>> { pub fn empty_filtered_deck(&mut self, did: DeckId) -> Result<OpOutput<()>> {
self.transact(Op::EmptyFilteredDeck, |col| { self.transact(Op::EmptyFilteredDeck, |col| {
col.return_all_cards_in_filtered_deck(did) col.return_all_cards_in_filtered_deck(did)
}) })
} }
// Unlike the old Python code, this also marks the cards as modified. // Unlike the old Python code, this also marks the cards as modified.
pub fn rebuild_filtered_deck(&mut self, did: DeckID) -> Result<OpOutput<usize>> { pub fn rebuild_filtered_deck(&mut self, did: DeckId) -> Result<OpOutput<usize>> {
self.transact(Op::RebuildFilteredDeck, |col| { self.transact(Op::RebuildFilteredDeck, |col| {
let deck = col.get_deck(did)?.ok_or(AnkiError::NotFound)?; let deck = col.get_deck(did)?.ok_or(AnkiError::NotFound)?;
col.rebuild_filtered_deck_inner(&deck, col.usn()?) col.rebuild_filtered_deck_inner(&deck, col.usn()?)
@ -77,13 +77,13 @@ impl Collection {
} }
impl Collection { impl Collection {
pub(crate) fn return_all_cards_in_filtered_deck(&mut self, did: DeckID) -> Result<()> { pub(crate) fn return_all_cards_in_filtered_deck(&mut self, did: DeckId) -> Result<()> {
let cids = self.storage.all_cards_in_single_deck(did)?; let cids = self.storage.all_cards_in_single_deck(did)?;
self.return_cards_to_home_deck(&cids) self.return_cards_to_home_deck(&cids)
} }
// Unlike the old Python code, this also marks the cards as modified. // Unlike the old Python code, this also marks the cards as modified.
fn return_cards_to_home_deck(&mut self, cids: &[CardID]) -> Result<()> { fn return_cards_to_home_deck(&mut self, cids: &[CardId]) -> Result<()> {
let sched = self.scheduler_version(); let sched = self.scheduler_version();
let usn = self.usn()?; let usn = self.usn()?;
for cid in cids { for cid in cids {
@ -150,7 +150,7 @@ impl Collection {
fn add_or_update_filtered_deck_inner( fn add_or_update_filtered_deck_inner(
&mut self, &mut self,
mut update: FilteredDeckForUpdate, mut update: FilteredDeckForUpdate,
) -> Result<DeckID> { ) -> Result<DeckId> {
let usn = self.usn()?; let usn = self.usn()?;
// check the searches are valid, and normalize them // check the searches are valid, and normalize them
@ -182,7 +182,7 @@ impl Collection {
Err(AnkiError::FilteredDeckEmpty) Err(AnkiError::FilteredDeckEmpty)
} else { } else {
// update current deck and return id // update current deck and return id
self.set_config(ConfigKey::CurrentDeckID, &deck.id)?; self.set_config(ConfigKey::CurrentDeckId, &deck.id)?;
Ok(deck.id) Ok(deck.id)
} }
} }

View File

@ -2,11 +2,11 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{ use crate::{
card::{Card, CardID, CardQueue, CardType}, card::{Card, CardId, CardQueue, CardType},
collection::Collection, collection::Collection,
decks::DeckID, decks::DeckId,
err::Result, err::Result,
notes::NoteID, notes::NoteId,
prelude::*, prelude::*,
search::SortMode, search::SortMode,
types::Usn, types::Usn,
@ -35,7 +35,7 @@ impl Card {
} }
} }
pub(crate) struct NewCardSorter { pub(crate) struct NewCardSorter {
position: HashMap<NoteID, u32>, position: HashMap<NoteId, u32>,
} }
#[derive(PartialEq)] #[derive(PartialEq)]
@ -71,7 +71,7 @@ impl NewCardSorter {
} }
} }
fn nids_in_desired_order(cards: &[Card], order: NewCardSortOrder) -> Vec<NoteID> { fn nids_in_desired_order(cards: &[Card], order: NewCardSortOrder) -> Vec<NoteId> {
if order == NewCardSortOrder::Preserve { if order == NewCardSortOrder::Preserve {
nids_in_preserved_order(cards) nids_in_preserved_order(cards)
} else { } else {
@ -90,7 +90,7 @@ fn nids_in_desired_order(cards: &[Card], order: NewCardSortOrder) -> Vec<NoteID>
} }
} }
fn nids_in_preserved_order(cards: &[Card]) -> Vec<NoteID> { fn nids_in_preserved_order(cards: &[Card]) -> Vec<NoteId> {
let mut seen = HashSet::new(); let mut seen = HashSet::new();
cards cards
.iter() .iter()
@ -105,7 +105,7 @@ fn nids_in_preserved_order(cards: &[Card]) -> Vec<NoteID> {
} }
impl Collection { impl Collection {
pub fn reschedule_cards_as_new(&mut self, cids: &[CardID], log: bool) -> Result<OpOutput<()>> { pub fn reschedule_cards_as_new(&mut self, cids: &[CardId], log: bool) -> Result<OpOutput<()>> {
let usn = self.usn()?; let usn = self.usn()?;
let mut position = self.get_next_card_position(); let mut position = self.get_next_card_position();
self.transact(Op::ScheduleAsNew, |col| { self.transact(Op::ScheduleAsNew, |col| {
@ -127,7 +127,7 @@ impl Collection {
pub fn sort_cards( pub fn sort_cards(
&mut self, &mut self,
cids: &[CardID], cids: &[CardId],
starting_from: u32, starting_from: u32,
step: u32, step: u32,
order: NewCardSortOrder, order: NewCardSortOrder,
@ -141,7 +141,7 @@ impl Collection {
fn sort_cards_inner( fn sort_cards_inner(
&mut self, &mut self,
cids: &[CardID], cids: &[CardId],
starting_from: u32, starting_from: u32,
step: u32, step: u32,
order: NewCardSortOrder, order: NewCardSortOrder,
@ -168,7 +168,7 @@ impl Collection {
/// This creates a transaction - we probably want to split it out /// This creates a transaction - we probably want to split it out
/// in the future if calling it as part of a deck options update. /// in the future if calling it as part of a deck options update.
pub fn sort_deck(&mut self, deck: DeckID, random: bool) -> Result<OpOutput<usize>> { pub fn sort_deck(&mut self, deck: DeckId, random: bool) -> Result<OpOutput<usize>> {
let cids = self.search_cards(&format!("did:{} is:new", deck), SortMode::NoOrder)?; let cids = self.search_cards(&format!("did:{} is:new", deck), SortMode::NoOrder)?;
let order = if random { let order = if random {
NewCardSortOrder::Random NewCardSortOrder::Random
@ -196,11 +196,11 @@ mod test {
#[test] #[test]
fn new_order() { fn new_order() {
let mut c1 = Card::new(NoteID(6), 0, DeckID(0), 0); let mut c1 = Card::new(NoteId(6), 0, DeckId(0), 0);
c1.id.0 = 2; c1.id.0 = 2;
let mut c2 = Card::new(NoteID(5), 0, DeckID(0), 0); let mut c2 = Card::new(NoteId(5), 0, DeckId(0), 0);
c2.id.0 = 3; c2.id.0 = 3;
let mut c3 = Card::new(NoteID(4), 0, DeckID(0), 0); let mut c3 = Card::new(NoteId(4), 0, DeckId(0), 0);
c3.id.0 = 1; c3.id.0 = 1;
let cards = vec![c1.clone(), c2.clone(), c3.clone()]; let cards = vec![c1.clone(), c2.clone(), c3.clone()];

View File

@ -100,12 +100,12 @@ impl QueueBuilder {
limit.new != 0 limit.new != 0
} }
fn should_add_review_card(&mut self, note_id: NoteID) -> bool { fn should_add_review_card(&mut self, note_id: NoteId) -> bool {
!self.have_seen_note_id(note_id) || !self.bury_reviews !self.have_seen_note_id(note_id) || !self.bury_reviews
} }
/// Mark note seen, and return true if seen before. /// Mark note seen, and return true if seen before.
fn have_seen_note_id(&mut self, note_id: NoteID) -> bool { fn have_seen_note_id(&mut self, note_id: NoteId) -> bool {
!self.seen_note_ids.insert(note_id) !self.seen_note_ids.insert(note_id)
} }
} }
@ -127,26 +127,26 @@ mod test {
let cards = vec![ let cards = vec![
NewCard { NewCard {
id: CardID(1), id: CardId(1),
note_id: NoteID(1), note_id: NoteId(1),
extra: 0, extra: 0,
..Default::default() ..Default::default()
}, },
NewCard { NewCard {
id: CardID(2), id: CardId(2),
note_id: NoteID(2), note_id: NoteId(2),
extra: 1, extra: 1,
..Default::default() ..Default::default()
}, },
NewCard { NewCard {
id: CardID(3), id: CardId(3),
note_id: NoteID(2), note_id: NoteId(2),
extra: 2, extra: 2,
..Default::default() ..Default::default()
}, },
NewCard { NewCard {
id: CardID(4), id: CardId(4),
note_id: NoteID(2), note_id: NoteId(2),
extra: 0, extra: 0,
..Default::default() ..Default::default()
}, },
@ -156,8 +156,8 @@ mod test {
builder.add_new_card(&mut limits, card.clone()); builder.add_new_card(&mut limits, card.clone());
} }
assert_eq!(builder.new[0].id, CardID(1)); assert_eq!(builder.new[0].id, CardId(1));
assert_eq!(builder.new[1].id, CardID(4)); assert_eq!(builder.new[1].id, CardId(4));
assert_eq!(builder.new.len(), 2); assert_eq!(builder.new.len(), 2);
// with burying disabled, we should get all siblings in order // with burying disabled, we should get all siblings in order
@ -168,9 +168,9 @@ mod test {
builder.add_new_card(&mut limits, card.clone()); builder.add_new_card(&mut limits, card.clone());
} }
assert_eq!(builder.new[0].id, CardID(1)); assert_eq!(builder.new[0].id, CardId(1));
assert_eq!(builder.new[1].id, CardID(4)); assert_eq!(builder.new[1].id, CardId(4));
assert_eq!(builder.new[2].id, CardID(2)); assert_eq!(builder.new[2].id, CardId(2));
assert_eq!(builder.new[3].id, CardID(3)); assert_eq!(builder.new[3].id, CardId(3));
} }
} }

View File

@ -22,8 +22,8 @@ use {intersperser::Intersperser, sized_chain::SizedChain};
/// Temporary holder for review cards that will be built into a queue. /// Temporary holder for review cards that will be built into a queue.
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub(crate) struct DueCard { pub(crate) struct DueCard {
pub id: CardID, pub id: CardId,
pub note_id: NoteID, pub note_id: NoteId,
pub mtime: TimestampSecs, pub mtime: TimestampSecs,
pub due: i32, pub due: i32,
pub interval: u32, pub interval: u32,
@ -33,8 +33,8 @@ pub(crate) struct DueCard {
/// Temporary holder for new cards that will be built into a queue. /// Temporary holder for new cards that will be built into a queue.
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub(crate) struct NewCard { pub(crate) struct NewCard {
pub id: CardID, pub id: CardId,
pub note_id: NoteID, pub note_id: NoteId,
pub mtime: TimestampSecs, pub mtime: TimestampSecs,
pub due: i32, pub due: i32,
/// Used to store template_idx, and for shuffling /// Used to store template_idx, and for shuffling
@ -77,7 +77,7 @@ pub(super) struct QueueBuilder {
pub(super) review: Vec<DueCard>, pub(super) review: Vec<DueCard>,
pub(super) learning: Vec<DueCard>, pub(super) learning: Vec<DueCard>,
pub(super) day_learning: Vec<DueCard>, pub(super) day_learning: Vec<DueCard>,
pub(super) seen_note_ids: HashSet<NoteID>, pub(super) seen_note_ids: HashSet<NoteId>,
pub(super) new_order: NewCardOrder, pub(super) new_order: NewCardOrder,
pub(super) review_order: ReviewCardOrder, pub(super) review_order: ReviewCardOrder,
pub(super) day_learn_mix: ReviewMix, pub(super) day_learn_mix: ReviewMix,
@ -91,7 +91,7 @@ impl QueueBuilder {
mut self, mut self,
top_deck_limits: RemainingLimits, top_deck_limits: RemainingLimits,
learn_ahead_secs: u32, learn_ahead_secs: u32,
selected_deck: DeckID, selected_deck: DeckId,
current_day: u32, current_day: u32,
) -> CardQueues { ) -> CardQueues {
self.sort_new(); self.sort_new();
@ -189,7 +189,7 @@ fn split_learning(
} }
impl Collection { impl Collection {
pub(crate) fn build_queues(&mut self, deck_id: DeckID) -> Result<CardQueues> { pub(crate) fn build_queues(&mut self, deck_id: DeckId) -> Result<CardQueues> {
let now = TimestampSecs::now(); let now = TimestampSecs::now();
let timing = self.timing_for_timestamp(now)?; let timing = self.timing_for_timestamp(now)?;
let (decks, parent_count) = self.storage.deck_with_parents_and_children(deck_id)?; let (decks, parent_count) = self.storage.deck_with_parents_and_children(deck_id)?;

View File

@ -12,7 +12,7 @@ pub(crate) enum QueueEntry {
} }
impl QueueEntry { impl QueueEntry {
pub fn card_id(&self) -> CardID { pub fn card_id(&self) -> CardId {
match self { match self {
QueueEntry::IntradayLearning(e) => e.id, QueueEntry::IntradayLearning(e) => e.id,
QueueEntry::Main(e) => e.id, QueueEntry::Main(e) => e.id,

View File

@ -13,7 +13,7 @@ use crate::{prelude::*, scheduler::timing::SchedTimingToday};
pub(crate) struct LearningQueueEntry { pub(crate) struct LearningQueueEntry {
// due comes first, so the derived ordering sorts by due // due comes first, so the derived ordering sorts by due
pub due: TimestampSecs, pub due: TimestampSecs,
pub id: CardID, pub id: CardId,
pub mtime: TimestampSecs, pub mtime: TimestampSecs,
} }
@ -37,7 +37,7 @@ impl CardQueues {
self.due_learning.front().copied() self.due_learning.front().copied()
} }
pub(super) fn pop_learning_entry(&mut self, id: CardID) -> Option<LearningQueueEntry> { pub(super) fn pop_learning_entry(&mut self, id: CardId) -> Option<LearningQueueEntry> {
if let Some(top) = self.due_learning.front() { if let Some(top) = self.due_learning.front() {
if top.id == id { if top.id == id {
self.counts.learning -= 1; self.counts.learning -= 1;
@ -135,7 +135,7 @@ impl CardQueues {
} }
} }
pub(super) fn remove_requeued_learning_card_after_undo(&mut self, id: CardID) { pub(super) fn remove_requeued_learning_card_after_undo(&mut self, id: CardId) {
let due_idx = self let due_idx = self
.due_learning .due_learning
.iter() .iter()

View File

@ -2,7 +2,7 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use super::{Deck, DeckKind}; use super::{Deck, DeckKind};
use crate::deckconf::{DeckConf, DeckConfID}; use crate::deckconf::{DeckConf, DeckConfId};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
@ -35,7 +35,7 @@ impl RemainingLimits {
pub(super) fn remaining_limits_capped_to_parents( pub(super) fn remaining_limits_capped_to_parents(
decks: &[Deck], decks: &[Deck],
config: &HashMap<DeckConfID, DeckConf>, config: &HashMap<DeckConfId, DeckConf>,
today: u32, today: u32,
) -> Vec<RemainingLimits> { ) -> Vec<RemainingLimits> {
let mut limits = get_remaining_limits(decks, config, today); let mut limits = get_remaining_limits(decks, config, today);
@ -47,7 +47,7 @@ pub(super) fn remaining_limits_capped_to_parents(
/// the provided deck order. /// the provided deck order.
fn get_remaining_limits( fn get_remaining_limits(
decks: &[Deck], decks: &[Deck],
config: &HashMap<DeckConfID, DeckConf>, config: &HashMap<DeckConfId, DeckConf>,
today: u32, today: u32,
) -> Vec<RemainingLimits> { ) -> Vec<RemainingLimits> {
decks decks
@ -55,7 +55,7 @@ fn get_remaining_limits(
.map(move |deck| { .map(move |deck| {
// get deck config if not filtered // get deck config if not filtered
let config = if let DeckKind::Normal(normal) = &deck.kind { let config = if let DeckKind::Normal(normal) = &deck.kind {
config.get(&DeckConfID(normal.config_id)) config.get(&DeckConfId(normal.config_id))
} else { } else {
None None
}; };

View File

@ -6,7 +6,7 @@ use crate::prelude::*;
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) struct MainQueueEntry { pub(crate) struct MainQueueEntry {
pub id: CardID, pub id: CardId,
pub mtime: TimestampSecs, pub mtime: TimestampSecs,
pub kind: MainQueueEntryKind, pub kind: MainQueueEntryKind,
} }
@ -22,7 +22,7 @@ impl CardQueues {
self.main.front().copied() self.main.front().copied()
} }
pub(super) fn pop_main_entry(&mut self, id: CardID) -> Option<MainQueueEntry> { pub(super) fn pop_main_entry(&mut self, id: CardId) -> Option<MainQueueEntry> {
if let Some(last) = self.main.front() { if let Some(last) = self.main.front() {
if last.id == id { if last.id == id {
match last.kind { match last.kind {

View File

@ -38,7 +38,7 @@ pub(crate) struct CardQueues {
later_learning: BinaryHeap<Reverse<LearningQueueEntry>>, later_learning: BinaryHeap<Reverse<LearningQueueEntry>>,
selected_deck: DeckID, selected_deck: DeckId,
current_day: u32, current_day: u32,
learn_ahead_secs: i64, learn_ahead_secs: i64,
} }
@ -76,7 +76,7 @@ impl CardQueues {
/// Remove the provided card from the top of the queues. /// Remove the provided card from the top of the queues.
/// If it was not at the top, return an error. /// If it was not at the top, return an error.
fn pop_answered(&mut self, id: CardID) -> Result<QueueEntry> { fn pop_answered(&mut self, id: CardId) -> Result<QueueEntry> {
if let Some(entry) = self.pop_undo_entry(id) { if let Some(entry) = self.pop_undo_entry(id) {
Ok(entry) Ok(entry)
} else if let Some(entry) = self.pop_main_entry(id) { } else if let Some(entry) = self.pop_main_entry(id) {
@ -92,7 +92,7 @@ impl CardQueues {
self.counts self.counts
} }
fn is_stale(&self, deck: DeckID, current_day: u32) -> bool { fn is_stale(&self, deck: DeckId, current_day: u32) -> bool {
self.selected_deck != deck || self.current_day != current_day self.selected_deck != deck || self.current_day != current_day
} }

View File

@ -51,7 +51,7 @@ impl CardQueues {
self.undo.last().copied() self.undo.last().copied()
} }
pub(super) fn pop_undo_entry(&mut self, id: CardID) -> Option<QueueEntry> { pub(super) fn pop_undo_entry(&mut self, id: CardId) -> Option<QueueEntry> {
if let Some(last) = self.undo.last() { if let Some(last) = self.undo.last() {
if last.card_id() == id { if last.card_id() == id {
match last.kind() { match last.kind() {

View File

@ -2,7 +2,7 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{ use crate::{
card::{Card, CardID, CardQueue, CardType}, card::{Card, CardId, CardQueue, CardType},
collection::Collection, collection::Collection,
config::StringKey, config::StringKey,
deckconf::INITIAL_EASE_FACTOR_THOUSANDS, deckconf::INITIAL_EASE_FACTOR_THOUSANDS,
@ -90,7 +90,7 @@ impl Collection {
/// value of `days`. /// value of `days`.
pub fn set_due_date( pub fn set_due_date(
&mut self, &mut self,
cids: &[CardID], cids: &[CardId],
days: &str, days: &str,
context: Option<StringKey>, context: Option<StringKey>,
) -> Result<OpOutput<()>> { ) -> Result<OpOutput<()>> {
@ -165,7 +165,7 @@ mod test {
#[test] #[test]
fn due_date() { fn due_date() {
let mut c = Card::new(NoteID(0), 0, DeckID(0), 0); let mut c = Card::new(NoteId(0), 0, DeckId(0), 0);
// setting the due date of a new card will convert it // setting the due date of a new card will convert it
c.set_due_date(5, 2, false); c.set_due_date(5, 2, false);
@ -191,7 +191,7 @@ mod test {
// should work in a filtered deck // should work in a filtered deck
c.interval = 2; c.interval = 2;
c.original_due = 7; c.original_due = 7;
c.original_deck_id = DeckID(1); c.original_deck_id = DeckId(1);
c.due = -10000; c.due = -10000;
c.queue = CardQueue::New; c.queue = CardQueue::New;
c.set_due_date(6, 1, false); c.set_due_date(6, 1, false);
@ -199,7 +199,7 @@ mod test {
assert_eq!(c.interval, 2); assert_eq!(c.interval, 2);
assert_eq!(c.queue, CardQueue::Review); assert_eq!(c.queue, CardQueue::Review);
assert_eq!(c.original_due, 0); assert_eq!(c.original_due, 0);
assert_eq!(c.original_deck_id, DeckID(0)); assert_eq!(c.original_deck_id, DeckId(0));
// relearning treated like review // relearning treated like review
c.ctype = CardType::Relearn; c.ctype = CardType::Relearn;

View File

@ -63,8 +63,8 @@ impl Card {
fn get_filter_info_for_card( fn get_filter_info_for_card(
card: &Card, card: &Card,
decks: &HashMap<DeckID, Deck>, decks: &HashMap<DeckId, Deck>,
configs: &HashMap<DeckConfID, DeckConf>, configs: &HashMap<DeckConfId, DeckConf>,
) -> Option<V1FilteredDeckInfo> { ) -> Option<V1FilteredDeckInfo> {
if card.original_deck_id.0 == 0 { if card.original_deck_id.0 == 0 {
None None
@ -85,7 +85,7 @@ fn get_filter_info_for_card(
let home_conf_id = decks let home_conf_id = decks
.get(&card.original_deck_id) .get(&card.original_deck_id)
.and_then(|deck| deck.config_id()) .and_then(|deck| deck.config_id())
.unwrap_or(DeckConfID(1)); .unwrap_or(DeckConfId(1));
Some( Some(
configs configs
.get(&home_conf_id) .get(&home_conf_id)

View File

@ -6,7 +6,7 @@ use super::{
sqlwriter::{RequiredTable, SqlWriter}, sqlwriter::{RequiredTable, SqlWriter},
}; };
use crate::{ use crate::{
card::CardID, card::CardId,
card::CardType, card::CardType,
collection::Collection, collection::Collection,
config::{BoolKey, SortKind}, config::{BoolKey, SortKind},
@ -60,7 +60,7 @@ impl SortKind {
} }
impl Collection { impl Collection {
pub fn search_cards(&mut self, search: &str, mut mode: SortMode) -> Result<Vec<CardID>> { pub fn search_cards(&mut self, search: &str, mut mode: SortMode) -> Result<Vec<CardId>> {
let top_node = Node::Group(parse(search)?); let top_node = Node::Group(parse(search)?);
self.resolve_config_sort(&mut mode); self.resolve_config_sort(&mut mode);
let writer = SqlWriter::new(self); let writer = SqlWriter::new(self);

View File

@ -4,11 +4,11 @@
use super::{parser::Node, sqlwriter::SqlWriter}; use super::{parser::Node, sqlwriter::SqlWriter};
use crate::collection::Collection; use crate::collection::Collection;
use crate::err::Result; use crate::err::Result;
use crate::notes::NoteID; use crate::notes::NoteId;
use crate::search::parser::parse; use crate::search::parser::parse;
impl Collection { impl Collection {
pub fn search_notes(&mut self, search: &str) -> Result<Vec<NoteID>> { pub fn search_notes(&mut self, search: &str) -> Result<Vec<NoteId>> {
let top_node = Node::Group(parse(search)?); let top_node = Node::Group(parse(search)?);
let writer = SqlWriter::new(self); let writer = SqlWriter::new(self);
let (sql, args) = writer.build_notes_query(&top_node)?; let (sql, args) = writer.build_notes_query(&top_node)?;

View File

@ -2,9 +2,9 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{ use crate::{
decks::DeckID, decks::DeckId,
err::{ParseError, Result, SearchErrorKind as FailKind}, err::{ParseError, Result, SearchErrorKind as FailKind},
notetype::NoteTypeID, notetype::NoteTypeId,
}; };
use lazy_static::lazy_static; use lazy_static::lazy_static;
use nom::{ use nom::{
@ -72,8 +72,8 @@ pub enum SearchNode {
EditedInDays(u32), EditedInDays(u32),
CardTemplate(TemplateKind), CardTemplate(TemplateKind),
Deck(String), Deck(String),
DeckID(DeckID), DeckId(DeckId),
NoteTypeID(NoteTypeID), NoteTypeId(NoteTypeId),
NoteType(String), NoteType(String),
Rated { Rated {
days: u32, days: u32,
@ -81,13 +81,13 @@ pub enum SearchNode {
}, },
Tag(String), Tag(String),
Duplicates { Duplicates {
note_type_id: NoteTypeID, note_type_id: NoteTypeId,
text: String, text: String,
}, },
State(StateKind), State(StateKind),
Flag(u8), Flag(u8),
NoteIDs(String), NoteIds(String),
CardIDs(String), CardIds(String),
Property { Property {
operator: String, operator: String,
kind: PropertyKind, kind: PropertyKind,
@ -337,8 +337,8 @@ fn search_node_for_text_with_argument<'a>(
"is" => parse_state(val)?, "is" => parse_state(val)?,
"did" => parse_did(val)?, "did" => parse_did(val)?,
"mid" => parse_mid(val)?, "mid" => parse_mid(val)?,
"nid" => SearchNode::NoteIDs(check_id_list(val, key)?.into()), "nid" => SearchNode::NoteIds(check_id_list(val, key)?.into()),
"cid" => SearchNode::CardIDs(check_id_list(val, key)?.into()), "cid" => SearchNode::CardIds(check_id_list(val, key)?.into()),
"re" => SearchNode::Regex(unescape_quotes(val)), "re" => SearchNode::Regex(unescape_quotes(val)),
"nc" => SearchNode::NoCombining(unescape(val)?), "nc" => SearchNode::NoCombining(unescape(val)?),
"w" => SearchNode::WordBoundary(unescape(val)?), "w" => SearchNode::WordBoundary(unescape(val)?),
@ -553,11 +553,11 @@ fn parse_state(s: &str) -> ParseResult<SearchNode> {
} }
fn parse_did(s: &str) -> ParseResult<SearchNode> { fn parse_did(s: &str) -> ParseResult<SearchNode> {
parse_i64(s, "did:").map(|n| SearchNode::DeckID(n.into())) parse_i64(s, "did:").map(|n| SearchNode::DeckId(n.into()))
} }
fn parse_mid(s: &str) -> ParseResult<SearchNode> { fn parse_mid(s: &str) -> ParseResult<SearchNode> {
parse_i64(s, "mid:").map(|n| SearchNode::NoteTypeID(n.into())) parse_i64(s, "mid:").map(|n| SearchNode::NoteTypeId(n.into()))
} }
/// ensure a list of ids contains only numbers and commas, returning unchanged if true /// ensure a list of ids contains only numbers and commas, returning unchanged if true
@ -833,7 +833,7 @@ mod test {
assert_eq!(parse("tag:hard")?, vec![Search(Tag("hard".into()))]); assert_eq!(parse("tag:hard")?, vec![Search(Tag("hard".into()))]);
assert_eq!( assert_eq!(
parse("nid:1237123712,2,3")?, parse("nid:1237123712,2,3")?,
vec![Search(NoteIDs("1237123712,2,3".into()))] vec![Search(NoteIds("1237123712,2,3".into()))]
); );
assert_eq!(parse("is:due")?, vec![Search(State(StateKind::Due))]); assert_eq!(parse("is:due")?, vec![Search(State(StateKind::Due))]);
assert_eq!(parse("flag:3")?, vec![Search(Flag(3))]); assert_eq!(parse("flag:3")?, vec![Search(Flag(3))]);

View File

@ -8,7 +8,7 @@ use crate::{
decks::human_deck_name_to_native, decks::human_deck_name_to_native,
err::Result, err::Result,
notes::field_checksum, notes::field_checksum,
notetype::NoteTypeID, notetype::NoteTypeId,
prelude::*, prelude::*,
storage::ids_to_string, storage::ids_to_string,
text::{ text::{
@ -140,10 +140,10 @@ impl SqlWriter<'_> {
} }
}, },
SearchNode::Deck(deck) => self.write_deck(&norm(deck))?, SearchNode::Deck(deck) => self.write_deck(&norm(deck))?,
SearchNode::NoteTypeID(ntid) => { SearchNode::NoteTypeId(ntid) => {
write!(self.sql, "n.mid = {}", ntid).unwrap(); write!(self.sql, "n.mid = {}", ntid).unwrap();
} }
SearchNode::DeckID(did) => { SearchNode::DeckId(did) => {
write!(self.sql, "c.did = {}", did).unwrap(); write!(self.sql, "c.did = {}", did).unwrap();
} }
SearchNode::NoteType(notetype) => self.write_note_type(&norm(notetype))?, SearchNode::NoteType(notetype) => self.write_note_type(&norm(notetype))?,
@ -154,10 +154,10 @@ impl SqlWriter<'_> {
SearchNode::Flag(flag) => { SearchNode::Flag(flag) => {
write!(self.sql, "(c.flags & 7) == {}", flag).unwrap(); write!(self.sql, "(c.flags & 7) == {}", flag).unwrap();
} }
SearchNode::NoteIDs(nids) => { SearchNode::NoteIds(nids) => {
write!(self.sql, "{} in ({})", self.note_id_column(), nids).unwrap(); write!(self.sql, "{} in ({})", self.note_id_column(), nids).unwrap();
} }
SearchNode::CardIDs(cids) => { SearchNode::CardIds(cids) => {
write!(self.sql, "c.id in ({})", cids).unwrap(); write!(self.sql, "c.id in ({})", cids).unwrap();
} }
SearchNode::Property { operator, kind } => self.write_prop(operator, kind)?, SearchNode::Property { operator, kind } => self.write_prop(operator, kind)?,
@ -461,7 +461,7 @@ impl SqlWriter<'_> {
Ok(()) Ok(())
} }
fn write_dupe(&mut self, ntid: NoteTypeID, text: &str) -> Result<()> { fn write_dupe(&mut self, ntid: NoteTypeId, text: &str) -> Result<()> {
let text_nohtml = strip_html_preserving_media_filenames(text); let text_nohtml = strip_html_preserving_media_filenames(text);
let csum = field_checksum(text_nohtml.as_ref()); let csum = field_checksum(text_nohtml.as_ref());
@ -554,11 +554,11 @@ impl SearchNode {
match self { match self {
SearchNode::AddedInDays(_) => RequiredTable::Cards, SearchNode::AddedInDays(_) => RequiredTable::Cards,
SearchNode::Deck(_) => RequiredTable::Cards, SearchNode::Deck(_) => RequiredTable::Cards,
SearchNode::DeckID(_) => RequiredTable::Cards, SearchNode::DeckId(_) => RequiredTable::Cards,
SearchNode::Rated { .. } => RequiredTable::Cards, SearchNode::Rated { .. } => RequiredTable::Cards,
SearchNode::State(_) => RequiredTable::Cards, SearchNode::State(_) => RequiredTable::Cards,
SearchNode::Flag(_) => RequiredTable::Cards, SearchNode::Flag(_) => RequiredTable::Cards,
SearchNode::CardIDs(_) => RequiredTable::Cards, SearchNode::CardIds(_) => RequiredTable::Cards,
SearchNode::Property { .. } => RequiredTable::Cards, SearchNode::Property { .. } => RequiredTable::Cards,
SearchNode::UnqualifiedText(_) => RequiredTable::Notes, SearchNode::UnqualifiedText(_) => RequiredTable::Notes,
@ -568,11 +568,11 @@ impl SearchNode {
SearchNode::Regex(_) => RequiredTable::Notes, SearchNode::Regex(_) => RequiredTable::Notes,
SearchNode::NoCombining(_) => RequiredTable::Notes, SearchNode::NoCombining(_) => RequiredTable::Notes,
SearchNode::WordBoundary(_) => RequiredTable::Notes, SearchNode::WordBoundary(_) => RequiredTable::Notes,
SearchNode::NoteTypeID(_) => RequiredTable::Notes, SearchNode::NoteTypeId(_) => RequiredTable::Notes,
SearchNode::NoteType(_) => RequiredTable::Notes, SearchNode::NoteType(_) => RequiredTable::Notes,
SearchNode::EditedInDays(_) => RequiredTable::Notes, SearchNode::EditedInDays(_) => RequiredTable::Notes,
SearchNode::NoteIDs(_) => RequiredTable::CardsOrNotes, SearchNode::NoteIds(_) => RequiredTable::CardsOrNotes,
SearchNode::WholeCollection => RequiredTable::CardsOrNotes, SearchNode::WholeCollection => RequiredTable::CardsOrNotes,
SearchNode::CardTemplate(_) => RequiredTable::CardsAndNotes, SearchNode::CardTemplate(_) => RequiredTable::CardsAndNotes,

View File

@ -2,8 +2,8 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{ use crate::{
decks::DeckID as DeckIDType, decks::DeckId as DeckIdType,
notetype::NoteTypeID as NoteTypeIDType, notetype::NoteTypeId as NoteTypeIdType,
prelude::*, prelude::*,
search::parser::{parse, Node, PropertyKind, RatingKind, SearchNode, StateKind, TemplateKind}, search::parser::{parse, Node, PropertyKind, RatingKind, SearchNode, StateKind, TemplateKind},
text::escape_anki_wildcards, text::escape_anki_wildcards,
@ -85,16 +85,16 @@ fn write_search_node(node: &SearchNode) -> String {
EditedInDays(u) => format!("\"edited:{}\"", u), EditedInDays(u) => format!("\"edited:{}\"", u),
CardTemplate(t) => write_template(t), CardTemplate(t) => write_template(t),
Deck(s) => quote(&format!("deck:{}", s)), Deck(s) => quote(&format!("deck:{}", s)),
DeckID(DeckIDType(i)) => format!("\"did:{}\"", i), DeckId(DeckIdType(i)) => format!("\"did:{}\"", i),
NoteTypeID(NoteTypeIDType(i)) => format!("\"mid:{}\"", i), NoteTypeId(NoteTypeIdType(i)) => format!("\"mid:{}\"", i),
NoteType(s) => quote(&format!("note:{}", s)), NoteType(s) => quote(&format!("note:{}", s)),
Rated { days, ease } => write_rated(days, ease), Rated { days, ease } => write_rated(days, ease),
Tag(s) => quote(&format!("tag:{}", s)), Tag(s) => quote(&format!("tag:{}", s)),
Duplicates { note_type_id, text } => write_dupe(note_type_id, text), Duplicates { note_type_id, text } => write_dupe(note_type_id, text),
State(k) => write_state(k), State(k) => write_state(k),
Flag(u) => format!("\"flag:{}\"", u), Flag(u) => format!("\"flag:{}\"", u),
NoteIDs(s) => format!("\"nid:{}\"", s), NoteIds(s) => format!("\"nid:{}\"", s),
CardIDs(s) => format!("\"cid:{}\"", s), CardIds(s) => format!("\"cid:{}\"", s),
Property { operator, kind } => write_property(operator, kind), Property { operator, kind } => write_property(operator, kind),
WholeCollection => "\"deck:*\"".to_string(), WholeCollection => "\"deck:*\"".to_string(),
Regex(s) => quote(&format!("re:{}", s)), Regex(s) => quote(&format!("re:{}", s)),
@ -135,7 +135,7 @@ fn write_rated(days: &u32, ease: &RatingKind) -> String {
} }
/// Escape double quotes and backslashes: \" /// Escape double quotes and backslashes: \"
fn write_dupe(note_type_id: &NoteTypeIDType, text: &str) -> String { fn write_dupe(note_type_id: &NoteTypeId, text: &str) -> String {
let esc = text.replace(r"\", r"\\").replace('"', r#"\""#); let esc = text.replace(r"\", r"\\").replace('"', r#"\""#);
format!("\"dupe:{},{}\"", note_type_id, esc) format!("\"dupe:{},{}\"", note_type_id, esc)
} }

View File

@ -25,8 +25,8 @@ struct CardStats {
card_type: String, card_type: String,
note_type: String, note_type: String,
deck: String, deck: String,
nid: NoteID, nid: NoteId,
cid: CardID, cid: CardId,
revlog: Vec<RevlogEntry>, revlog: Vec<RevlogEntry>,
} }
@ -56,12 +56,12 @@ struct RevlogText {
} }
impl Collection { impl Collection {
pub fn card_stats(&mut self, cid: CardID) -> Result<String> { pub fn card_stats(&mut self, cid: CardId) -> Result<String> {
let stats = self.gather_card_stats(cid)?; let stats = self.gather_card_stats(cid)?;
self.card_stats_to_string(stats) self.card_stats_to_string(stats)
} }
fn gather_card_stats(&mut self, cid: CardID) -> Result<CardStats> { fn gather_card_stats(&mut self, cid: CardId) -> Result<CardStats> {
let card = self.storage.get_card(cid)?.ok_or(AnkiError::NotFound)?; let card = self.storage.get_card(cid)?.ok_or(AnkiError::NotFound)?;
let note = self let note = self
.storage .storage
@ -265,7 +265,7 @@ mod test {
let nt = col.get_notetype_by_name("Basic")?.unwrap(); let nt = col.get_notetype_by_name("Basic")?.unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
let cid = col.search_cards("", SortMode::NoOrder)?[0]; let cid = col.search_cards("", SortMode::NoOrder)?[0];
let _report = col.card_stats(cid)?; let _report = col.card_stats(cid)?;

View File

@ -4,11 +4,11 @@
pub(crate) mod filtered; pub(crate) mod filtered;
use crate::{ use crate::{
card::{Card, CardID, CardQueue, CardType}, card::{Card, CardId, CardQueue, CardType},
deckconf::DeckConfID, deckconf::DeckConfId,
decks::{Deck, DeckID, DeckKind}, decks::{Deck, DeckId, DeckKind},
err::Result, err::Result,
notes::NoteID, notes::NoteId,
scheduler::{ scheduler::{
congrats::CongratsInfo, congrats::CongratsInfo,
queue::{DueCard, NewCard}, queue::{DueCard, NewCard},
@ -70,7 +70,7 @@ fn row_to_card(row: &Row) -> result::Result<Card, rusqlite::Error> {
} }
impl super::SqliteStorage { impl super::SqliteStorage {
pub fn get_card(&self, cid: CardID) -> Result<Option<Card>> { pub fn get_card(&self, cid: CardId) -> Result<Option<Card>> {
self.db self.db
.prepare_cached(concat!(include_str!("get_card.sql"), " where id = ?"))? .prepare_cached(concat!(include_str!("get_card.sql"), " where id = ?"))?
.query_row(params![cid], row_to_card) .query_row(params![cid], row_to_card)
@ -126,7 +126,7 @@ impl super::SqliteStorage {
card.flags, card.flags,
card.data, card.data,
])?; ])?;
card.id = CardID(self.db.last_insert_rowid()); card.id = CardId(self.db.last_insert_rowid());
Ok(()) Ok(())
} }
@ -157,7 +157,7 @@ impl super::SqliteStorage {
Ok(()) Ok(())
} }
pub(crate) fn remove_card(&self, cid: CardID) -> Result<()> { pub(crate) fn remove_card(&self, cid: CardId) -> Result<()> {
self.db self.db
.prepare_cached("delete from cards where id = ?")? .prepare_cached("delete from cards where id = ?")?
.execute(&[cid])?; .execute(&[cid])?;
@ -170,7 +170,7 @@ impl super::SqliteStorage {
&self, &self,
day_cutoff: u32, day_cutoff: u32,
learn_cutoff: i64, learn_cutoff: i64,
deck: DeckID, deck: DeckId,
mut func: F, mut func: F,
) -> Result<()> ) -> Result<()>
where where
@ -205,7 +205,7 @@ impl super::SqliteStorage {
/// Call func() for each new card, stopping when it returns false /// Call func() for each new card, stopping when it returns false
/// or no more cards found. Cards will arrive in (deck_id, due) order. /// or no more cards found. Cards will arrive in (deck_id, due) order.
pub(crate) fn for_each_new_card_in_deck<F>(&self, deck: DeckID, mut func: F) -> Result<()> pub(crate) fn for_each_new_card_in_deck<F>(&self, deck: DeckId, mut func: F) -> Result<()>
where where
F: FnMut(NewCard) -> bool, F: FnMut(NewCard) -> bool,
{ {
@ -260,7 +260,7 @@ impl super::SqliteStorage {
.map_err(Into::into) .map_err(Into::into)
} }
pub(crate) fn all_filtered_cards_by_deck(&self) -> Result<Vec<(CardID, DeckID)>> { pub(crate) fn all_filtered_cards_by_deck(&self) -> Result<Vec<(CardId, DeckId)>> {
self.db self.db
.prepare("select id, did from cards where odid > 0")? .prepare("select id, did from cards where odid > 0")?
.query_and_then(NO_PARAMS, |r| -> Result<_> { Ok((r.get(0)?, r.get(1)?)) })? .query_and_then(NO_PARAMS, |r| -> Result<_> { Ok((r.get(0)?, r.get(1)?)) })?
@ -274,7 +274,7 @@ impl super::SqliteStorage {
.map_err(Into::into) .map_err(Into::into)
} }
pub(crate) fn get_card_by_ordinal(&self, nid: NoteID, ord: u16) -> Result<Option<Card>> { pub(crate) fn get_card_by_ordinal(&self, nid: NoteId, ord: u16) -> Result<Option<Card>> {
self.db self.db
.prepare_cached(concat!( .prepare_cached(concat!(
include_str!("get_card.sql"), include_str!("get_card.sql"),
@ -301,25 +301,25 @@ impl super::SqliteStorage {
.map_err(Into::into) .map_err(Into::into)
} }
pub(crate) fn all_cards_of_note(&self, nid: NoteID) -> Result<Vec<Card>> { pub(crate) fn all_cards_of_note(&self, nid: NoteId) -> Result<Vec<Card>> {
self.db self.db
.prepare_cached(concat!(include_str!("get_card.sql"), " where nid = ?"))? .prepare_cached(concat!(include_str!("get_card.sql"), " where nid = ?"))?
.query_and_then(&[nid], |r| row_to_card(r).map_err(Into::into))? .query_and_then(&[nid], |r| row_to_card(r).map_err(Into::into))?
.collect() .collect()
} }
pub(crate) fn all_card_ids_of_note(&self, nid: NoteID) -> Result<Vec<CardID>> { pub(crate) fn all_card_ids_of_note(&self, nid: NoteId) -> Result<Vec<CardId>> {
self.db self.db
.prepare_cached("select id from cards where nid = ? order by ord")? .prepare_cached("select id from cards where nid = ? order by ord")?
.query_and_then(&[nid], |r| Ok(CardID(r.get(0)?)))? .query_and_then(&[nid], |r| Ok(CardId(r.get(0)?)))?
.collect() .collect()
} }
/// Place matching card ids into the search table. /// Place matching card ids into the search table.
pub(crate) fn search_siblings_for_bury( pub(crate) fn search_siblings_for_bury(
&self, &self,
cid: CardID, cid: CardId,
nid: NoteID, nid: NoteId,
include_new: bool, include_new: bool,
include_reviews: bool, include_reviews: bool,
) -> Result<()> { ) -> Result<()> {
@ -337,14 +337,14 @@ impl super::SqliteStorage {
Ok(()) Ok(())
} }
pub(crate) fn note_ids_of_cards(&self, cids: &[CardID]) -> Result<HashSet<NoteID>> { pub(crate) fn note_ids_of_cards(&self, cids: &[CardId]) -> Result<HashSet<NoteId>> {
let mut stmt = self let mut stmt = self
.db .db
.prepare_cached("select nid from cards where id = ?")?; .prepare_cached("select nid from cards where id = ?")?;
let mut nids = HashSet::new(); let mut nids = HashSet::new();
for cid in cids { for cid in cids {
if let Some(nid) = stmt if let Some(nid) = stmt
.query_row(&[cid], |r| r.get::<_, NoteID>(0)) .query_row(&[cid], |r| r.get::<_, NoteId>(0))
.optional()? .optional()?
{ {
nids.insert(nid); nids.insert(nid);
@ -451,7 +451,7 @@ impl super::SqliteStorage {
/// Clear with clear_searched_cards_table(). /// Clear with clear_searched_cards_table().
pub(crate) fn set_search_table_to_card_ids( pub(crate) fn set_search_table_to_card_ids(
&mut self, &mut self,
cards: &[CardID], cards: &[CardId],
preserve_order: bool, preserve_order: bool,
) -> Result<()> { ) -> Result<()> {
if preserve_order { if preserve_order {
@ -474,7 +474,7 @@ impl super::SqliteStorage {
/// 130% when the deck options were edited for the first time. /// 130% when the deck options were edited for the first time.
pub(crate) fn fix_low_card_eases_for_configs( pub(crate) fn fix_low_card_eases_for_configs(
&self, &self,
configs: &[DeckConfID], configs: &[DeckConfId],
server: bool, server: bool,
) -> Result<()> { ) -> Result<()> {
let mut affected_decks = vec![]; let mut affected_decks = vec![];

View File

@ -3,12 +3,12 @@
use super::SqliteStorage; use super::SqliteStorage;
use crate::{ use crate::{
card::CardID, card::CardId,
card::CardQueue, card::CardQueue,
config::SchedulerVersion, config::SchedulerVersion,
decks::immediate_parent_name, decks::immediate_parent_name,
decks::{Deck, DeckCommon, DeckID, DeckKindProto, DeckSchema11, DueCounts}, decks::{Deck, DeckCommon, DeckId, DeckKindProto, DeckSchema11, DueCounts},
err::{AnkiError, DBErrorKind, Result}, err::{AnkiError, DbErrorKind, Result},
i18n::I18n, i18n::I18n,
timestamp::TimestampMillis, timestamp::TimestampMillis,
}; };
@ -27,14 +27,14 @@ fn row_to_deck(row: &Row) -> Result<Deck> {
mtime_secs: row.get(2)?, mtime_secs: row.get(2)?,
usn: row.get(3)?, usn: row.get(3)?,
common, common,
kind: kind.kind.ok_or_else(|| AnkiError::DBError { kind: kind.kind.ok_or_else(|| AnkiError::DbError {
kind: DBErrorKind::MissingEntity, kind: DbErrorKind::MissingEntity,
info: format!("invalid deck kind: {}", id), info: format!("invalid deck kind: {}", id),
})?, })?,
}) })
} }
fn row_to_due_counts(row: &Row) -> Result<(DeckID, DueCounts)> { fn row_to_due_counts(row: &Row) -> Result<(DeckId, DueCounts)> {
Ok(( Ok((
row.get(0)?, row.get(0)?,
DueCounts { DueCounts {
@ -46,12 +46,12 @@ fn row_to_due_counts(row: &Row) -> Result<(DeckID, DueCounts)> {
} }
impl SqliteStorage { impl SqliteStorage {
pub(crate) fn get_all_decks_as_schema11(&self) -> Result<HashMap<DeckID, DeckSchema11>> { pub(crate) fn get_all_decks_as_schema11(&self) -> Result<HashMap<DeckId, DeckSchema11>> {
self.get_all_decks() self.get_all_decks()
.map(|r| r.into_iter().map(|d| (d.id, d.into())).collect()) .map(|r| r.into_iter().map(|d| (d.id, d.into())).collect())
} }
pub(crate) fn get_deck(&self, did: DeckID) -> Result<Option<Deck>> { pub(crate) fn get_deck(&self, did: DeckId) -> Result<Option<Deck>> {
self.db self.db
.prepare_cached(concat!(include_str!("get_deck.sql"), " where id = ?"))? .prepare_cached(concat!(include_str!("get_deck.sql"), " where id = ?"))?
.query_and_then(&[did], row_to_deck)? .query_and_then(&[did], row_to_deck)?
@ -66,7 +66,7 @@ impl SqliteStorage {
.collect() .collect()
} }
pub(crate) fn get_decks_map(&self) -> Result<HashMap<DeckID, Deck>> { pub(crate) fn get_decks_map(&self) -> Result<HashMap<DeckId, Deck>> {
self.db self.db
.prepare(include_str!("get_deck.sql"))? .prepare(include_str!("get_deck.sql"))?
.query_and_then(NO_PARAMS, row_to_deck)? .query_and_then(NO_PARAMS, row_to_deck)?
@ -75,7 +75,7 @@ impl SqliteStorage {
} }
/// Get all deck names in sorted, human-readable form (::) /// Get all deck names in sorted, human-readable form (::)
pub(crate) fn get_all_deck_names(&self) -> Result<Vec<(DeckID, String)>> { pub(crate) fn get_all_deck_names(&self) -> Result<Vec<(DeckId, String)>> {
self.db self.db
.prepare("select id, name from decks order by name")? .prepare("select id, name from decks order by name")?
.query_and_then(NO_PARAMS, |row| { .query_and_then(NO_PARAMS, |row| {
@ -84,7 +84,7 @@ impl SqliteStorage {
.collect() .collect()
} }
pub(crate) fn get_deck_id(&self, machine_name: &str) -> Result<Option<DeckID>> { pub(crate) fn get_deck_id(&self, machine_name: &str) -> Result<Option<DeckId>> {
self.db self.db
.prepare("select id from decks where name = ?")? .prepare("select id from decks where name = ?")?
.query_and_then(&[machine_name], |row| row.get(0))? .query_and_then(&[machine_name], |row| row.get(0))?
@ -166,14 +166,14 @@ impl SqliteStorage {
Ok(()) Ok(())
} }
pub(crate) fn remove_deck(&self, did: DeckID) -> Result<()> { pub(crate) fn remove_deck(&self, did: DeckId) -> Result<()> {
self.db self.db
.prepare_cached("delete from decks where id = ?")? .prepare_cached("delete from decks where id = ?")?
.execute(&[did])?; .execute(&[did])?;
Ok(()) Ok(())
} }
pub(crate) fn all_cards_in_single_deck(&self, did: DeckID) -> Result<Vec<CardID>> { pub(crate) fn all_cards_in_single_deck(&self, did: DeckId) -> Result<Vec<CardId>> {
self.db self.db
.prepare_cached(include_str!("cards_for_deck.sql"))? .prepare_cached(include_str!("cards_for_deck.sql"))?
.query_and_then(&[did], |r| r.get(0).map_err(Into::into))? .query_and_then(&[did], |r| r.get(0).map_err(Into::into))?
@ -196,7 +196,7 @@ impl SqliteStorage {
/// the number of parent decks that need to be skipped to get to the chosen deck. /// the number of parent decks that need to be skipped to get to the chosen deck.
pub(crate) fn deck_with_parents_and_children( pub(crate) fn deck_with_parents_and_children(
&self, &self,
deck_id: DeckID, deck_id: DeckId,
) -> Result<(Vec<Deck>, usize)> { ) -> Result<(Vec<Deck>, usize)> {
let deck = self.get_deck(deck_id)?.ok_or(AnkiError::NotFound)?; let deck = self.get_deck(deck_id)?.ok_or(AnkiError::NotFound)?;
let mut parents = self.parent_decks(&deck)?; let mut parents = self.parent_decks(&deck)?;
@ -247,7 +247,7 @@ impl SqliteStorage {
day_cutoff: u32, day_cutoff: u32,
learn_cutoff: u32, learn_cutoff: u32,
top_deck: Option<&str>, top_deck: Option<&str>,
) -> Result<HashMap<DeckID, DueCounts>> { ) -> Result<HashMap<DeckId, DueCounts>> {
let sched_ver = sched as u8; let sched_ver = sched as u8;
let mut params = named_params! { let mut params = named_params! {
":new_queue": CardQueue::New as u8, ":new_queue": CardQueue::New as u8,
@ -292,14 +292,14 @@ impl SqliteStorage {
} }
/// Decks referenced by cards but missing. /// Decks referenced by cards but missing.
pub(crate) fn missing_decks(&self) -> Result<Vec<DeckID>> { pub(crate) fn missing_decks(&self) -> Result<Vec<DeckId>> {
self.db self.db
.prepare(include_str!("missing-decks.sql"))? .prepare(include_str!("missing-decks.sql"))?
.query_and_then(NO_PARAMS, |r| r.get(0).map_err(Into::into))? .query_and_then(NO_PARAMS, |r| r.get(0).map_err(Into::into))?
.collect() .collect()
} }
pub(crate) fn deck_is_empty(&self, did: DeckID) -> Result<bool> { pub(crate) fn deck_is_empty(&self, did: DeckId) -> Result<bool> {
self.db self.db
.prepare_cached("select null from cards where did=?")? .prepare_cached("select null from cards where did=?")?
.query(&[did])? .query(&[did])?
@ -373,23 +373,23 @@ impl SqliteStorage {
self.set_schema11_decks(decks) self.set_schema11_decks(decks)
} }
fn get_schema11_decks(&self) -> Result<HashMap<DeckID, DeckSchema11>> { fn get_schema11_decks(&self) -> Result<HashMap<DeckId, DeckSchema11>> {
let mut stmt = self.db.prepare("select decks from col")?; let mut stmt = self.db.prepare("select decks from col")?;
let decks = stmt let decks = stmt
.query_and_then(NO_PARAMS, |row| -> Result<HashMap<DeckID, DeckSchema11>> { .query_and_then(NO_PARAMS, |row| -> Result<HashMap<DeckId, DeckSchema11>> {
let v: HashMap<DeckID, DeckSchema11> = let v: HashMap<DeckId, DeckSchema11> =
serde_json::from_str(row.get_raw(0).as_str()?)?; serde_json::from_str(row.get_raw(0).as_str()?)?;
Ok(v) Ok(v)
})? })?
.next() .next()
.ok_or_else(|| AnkiError::DBError { .ok_or_else(|| AnkiError::DbError {
info: "col table empty".to_string(), info: "col table empty".to_string(),
kind: DBErrorKind::MissingEntity, kind: DbErrorKind::MissingEntity,
})??; })??;
Ok(decks) Ok(decks)
} }
pub(crate) fn set_schema11_decks(&self, decks: HashMap<DeckID, DeckSchema11>) -> Result<()> { pub(crate) fn set_schema11_decks(&self, decks: HashMap<DeckId, DeckSchema11>) -> Result<()> {
let json = serde_json::to_string(&decks)?; let json = serde_json::to_string(&decks)?;
self.db.execute("update col set decks = ?", &[json])?; self.db.execute("update col set decks = ?", &[json])?;
Ok(()) Ok(())

View File

@ -3,7 +3,7 @@
use super::SqliteStorage; use super::SqliteStorage;
use crate::{ use crate::{
deckconf::{DeckConf, DeckConfID, DeckConfSchema11, DeckConfigInner}, deckconf::{DeckConf, DeckConfId, DeckConfSchema11, DeckConfigInner},
err::Result, err::Result,
i18n::I18n, i18n::I18n,
}; };
@ -31,7 +31,7 @@ impl SqliteStorage {
.collect() .collect()
} }
pub(crate) fn get_deck_config_map(&self) -> Result<HashMap<DeckConfID, DeckConf>> { pub(crate) fn get_deck_config_map(&self) -> Result<HashMap<DeckConfId, DeckConf>> {
self.db self.db
.prepare_cached(include_str!("get.sql"))? .prepare_cached(include_str!("get.sql"))?
.query_and_then(NO_PARAMS, row_to_deckconf)? .query_and_then(NO_PARAMS, row_to_deckconf)?
@ -39,7 +39,7 @@ impl SqliteStorage {
.collect() .collect()
} }
pub(crate) fn get_deck_config(&self, dcid: DeckConfID) -> Result<Option<DeckConf>> { pub(crate) fn get_deck_config(&self, dcid: DeckConfId) -> Result<Option<DeckConf>> {
self.db self.db
.prepare_cached(concat!(include_str!("get.sql"), " where id = ?"))? .prepare_cached(concat!(include_str!("get.sql"), " where id = ?"))?
.query_and_then(params![dcid], row_to_deckconf)? .query_and_then(params![dcid], row_to_deckconf)?
@ -97,7 +97,7 @@ impl SqliteStorage {
Ok(()) Ok(())
} }
pub(crate) fn remove_deck_conf(&self, dcid: DeckConfID) -> Result<()> { pub(crate) fn remove_deck_conf(&self, dcid: DeckConfId) -> Result<()> {
self.db self.db
.prepare_cached("delete from deck_config where id=?")? .prepare_cached("delete from deck_config where id=?")?
.execute(params![dcid])?; .execute(params![dcid])?;
@ -140,7 +140,7 @@ impl SqliteStorage {
} }
pub(super) fn upgrade_deck_conf_to_schema14(&self) -> Result<()> { pub(super) fn upgrade_deck_conf_to_schema14(&self) -> Result<()> {
let conf: HashMap<DeckConfID, DeckConfSchema11> = let conf: HashMap<DeckConfId, DeckConfSchema11> =
self.db self.db
.query_row_and_then("select dconf from col", NO_PARAMS, |row| -> Result<_> { .query_row_and_then("select dconf from col", NO_PARAMS, |row| -> Result<_> {
let text = row.get_raw(0).as_str()?; let text = row.get_raw(0).as_str()?;
@ -208,7 +208,7 @@ impl SqliteStorage {
pub(super) fn downgrade_deck_conf_from_schema16(&self) -> Result<()> { pub(super) fn downgrade_deck_conf_from_schema16(&self) -> Result<()> {
let allconf = self.all_deck_config()?; let allconf = self.all_deck_config()?;
let confmap: HashMap<DeckConfID, DeckConfSchema11> = allconf let confmap: HashMap<DeckConfId, DeckConfSchema11> = allconf
.into_iter() .into_iter()
.map(|c| -> DeckConfSchema11 { c.into() }) .map(|c| -> DeckConfSchema11 { c.into() })
.map(|c| (c.id, c)) .map(|c| (c.id, c))

View File

@ -3,10 +3,10 @@
use super::SqliteStorage; use super::SqliteStorage;
use crate::{ use crate::{
card::CardID, card::CardId,
decks::DeckID, decks::DeckId,
err::{AnkiError, Result}, err::{AnkiError, Result},
notes::NoteID, notes::NoteId,
sync::Graves, sync::Graves,
types::Usn, types::Usn,
}; };
@ -28,27 +28,27 @@ impl SqliteStorage {
Ok(()) Ok(())
} }
pub(crate) fn add_card_grave(&self, cid: CardID, usn: Usn) -> Result<()> { pub(crate) fn add_card_grave(&self, cid: CardId, usn: Usn) -> Result<()> {
self.add_grave(cid.0, GraveKind::Card, usn) self.add_grave(cid.0, GraveKind::Card, usn)
} }
pub(crate) fn add_note_grave(&self, nid: NoteID, usn: Usn) -> Result<()> { pub(crate) fn add_note_grave(&self, nid: NoteId, usn: Usn) -> Result<()> {
self.add_grave(nid.0, GraveKind::Note, usn) self.add_grave(nid.0, GraveKind::Note, usn)
} }
pub(crate) fn add_deck_grave(&self, did: DeckID, usn: Usn) -> Result<()> { pub(crate) fn add_deck_grave(&self, did: DeckId, usn: Usn) -> Result<()> {
self.add_grave(did.0, GraveKind::Deck, usn) self.add_grave(did.0, GraveKind::Deck, usn)
} }
pub(crate) fn remove_card_grave(&self, cid: CardID) -> Result<()> { pub(crate) fn remove_card_grave(&self, cid: CardId) -> Result<()> {
self.remove_grave(cid.0, GraveKind::Card) self.remove_grave(cid.0, GraveKind::Card)
} }
pub(crate) fn remove_note_grave(&self, nid: NoteID) -> Result<()> { pub(crate) fn remove_note_grave(&self, nid: NoteId) -> Result<()> {
self.remove_grave(nid.0, GraveKind::Note) self.remove_grave(nid.0, GraveKind::Note)
} }
pub(crate) fn remove_deck_grave(&self, did: DeckID) -> Result<()> { pub(crate) fn remove_deck_grave(&self, did: DeckId) -> Result<()> {
self.remove_grave(did.0, GraveKind::Deck) self.remove_grave(did.0, GraveKind::Deck)
} }
@ -64,9 +64,9 @@ impl SqliteStorage {
let kind = GraveKind::try_from(row.get::<_, u8>(1)?) let kind = GraveKind::try_from(row.get::<_, u8>(1)?)
.map_err(|_| AnkiError::invalid_input("invalid grave kind"))?; .map_err(|_| AnkiError::invalid_input("invalid grave kind"))?;
match kind { match kind {
GraveKind::Card => graves.cards.push(CardID(oid)), GraveKind::Card => graves.cards.push(CardId(oid)),
GraveKind::Note => graves.notes.push(NoteID(oid)), GraveKind::Note => graves.notes.push(NoteId(oid)),
GraveKind::Deck => graves.decks.push(DeckID(oid)), GraveKind::Deck => graves.decks.push(DeckId(oid)),
} }
} }
Ok(graves) Ok(graves)

View File

@ -5,8 +5,8 @@ use std::collections::HashSet;
use crate::{ use crate::{
err::Result, err::Result,
notes::{Note, NoteID, NoteTags}, notes::{Note, NoteId, NoteTags},
notetype::NoteTypeID, notetype::NoteTypeId,
tags::{join_tags, split_tags}, tags::{join_tags, split_tags},
timestamp::TimestampMillis, timestamp::TimestampMillis,
}; };
@ -21,7 +21,7 @@ pub(crate) fn join_fields(fields: &[String]) -> String {
} }
impl super::SqliteStorage { impl super::SqliteStorage {
pub fn get_note(&self, nid: NoteID) -> Result<Option<Note>> { pub fn get_note(&self, nid: NoteId) -> Result<Option<Note>> {
self.db self.db
.prepare_cached(concat!(include_str!("get.sql"), " where id = ?"))? .prepare_cached(concat!(include_str!("get.sql"), " where id = ?"))?
.query_and_then(params![nid], row_to_note)? .query_and_then(params![nid], row_to_note)?
@ -29,7 +29,7 @@ impl super::SqliteStorage {
.transpose() .transpose()
} }
pub fn get_note_without_fields(&self, nid: NoteID) -> Result<Option<Note>> { pub fn get_note_without_fields(&self, nid: NoteId) -> Result<Option<Note>> {
self.db self.db
.prepare_cached(concat!( .prepare_cached(concat!(
include_str!("get_without_fields.sql"), include_str!("get_without_fields.sql"),
@ -93,14 +93,14 @@ impl super::SqliteStorage {
Ok(()) Ok(())
} }
pub(crate) fn remove_note(&self, nid: NoteID) -> Result<()> { pub(crate) fn remove_note(&self, nid: NoteId) -> Result<()> {
self.db self.db
.prepare_cached("delete from notes where id = ?")? .prepare_cached("delete from notes where id = ?")?
.execute(&[nid])?; .execute(&[nid])?;
Ok(()) Ok(())
} }
pub(crate) fn note_is_orphaned(&self, nid: NoteID) -> Result<bool> { pub(crate) fn note_is_orphaned(&self, nid: NoteId) -> Result<bool> {
self.db self.db
.prepare_cached(include_str!("is_orphaned.sql"))? .prepare_cached(include_str!("is_orphaned.sql"))?
.query_row(&[nid], |r| r.get(0)) .query_row(&[nid], |r| r.get(0))
@ -114,7 +114,7 @@ impl super::SqliteStorage {
Ok(()) Ok(())
} }
pub(crate) fn fix_invalid_utf8_in_note(&self, nid: NoteID) -> Result<()> { pub(crate) fn fix_invalid_utf8_in_note(&self, nid: NoteId) -> Result<()> {
self.db self.db
.query_row( .query_row(
"select cast(flds as blob) from notes where id=?", "select cast(flds as blob) from notes where id=?",
@ -137,9 +137,9 @@ impl super::SqliteStorage {
/// match. /// match.
pub(crate) fn note_fields_by_checksum( pub(crate) fn note_fields_by_checksum(
&self, &self,
ntid: NoteTypeID, ntid: NoteTypeId,
csum: u32, csum: u32,
) -> Result<Vec<(NoteID, String)>> { ) -> Result<Vec<(NoteId, String)>> {
self.db self.db
.prepare("select id, field_at_index(flds, 0) from notes where csum=? and mid=?")? .prepare("select id, field_at_index(flds, 0) from notes where csum=? and mid=?")?
.query_and_then(params![csum, ntid], |r| Ok((r.get(0)?, r.get(1)?)))? .query_and_then(params![csum, ntid], |r| Ok((r.get(0)?, r.get(1)?)))?
@ -170,7 +170,7 @@ impl super::SqliteStorage {
Ok(seen) Ok(seen)
} }
pub(crate) fn get_note_tags_by_id(&mut self, note_id: NoteID) -> Result<Option<NoteTags>> { pub(crate) fn get_note_tags_by_id(&mut self, note_id: NoteId) -> Result<Option<NoteTags>> {
self.db self.db
.prepare_cached(&format!("{} where id = ?", include_str!("get_tags.sql")))? .prepare_cached(&format!("{} where id = ?", include_str!("get_tags.sql")))?
.query_and_then(&[note_id], row_to_note_tags)? .query_and_then(&[note_id], row_to_note_tags)?
@ -180,7 +180,7 @@ impl super::SqliteStorage {
pub(crate) fn get_note_tags_by_id_list( pub(crate) fn get_note_tags_by_id_list(
&mut self, &mut self,
note_ids: &[NoteID], note_ids: &[NoteId],
) -> Result<Vec<NoteTags>> { ) -> Result<Vec<NoteTags>> {
self.set_search_table_to_note_ids(note_ids)?; self.set_search_table_to_note_ids(note_ids)?;
let out = self let out = self
@ -233,7 +233,7 @@ impl super::SqliteStorage {
/// Injects the provided card IDs into the search_nids table, for /// Injects the provided card IDs into the search_nids table, for
/// when ids have arrived outside of a search. /// when ids have arrived outside of a search.
/// Clear with clear_searched_notes_table(). /// Clear with clear_searched_notes_table().
fn set_search_table_to_note_ids(&mut self, notes: &[NoteID]) -> Result<()> { fn set_search_table_to_note_ids(&mut self, notes: &[NoteId]) -> Result<()> {
self.setup_searched_notes_table()?; self.setup_searched_notes_table()?;
let mut stmt = self let mut stmt = self
.db .db

View File

@ -3,13 +3,13 @@
use super::{ids_to_string, SqliteStorage}; use super::{ids_to_string, SqliteStorage};
use crate::{ use crate::{
err::{AnkiError, DBErrorKind, Result}, err::{AnkiError, DbErrorKind, Result},
notes::NoteID, notes::NoteId,
notetype::{ notetype::{
AlreadyGeneratedCardInfo, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, AlreadyGeneratedCardInfo, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig,
NoteTypeConfig, NoteTypeConfig,
}, },
notetype::{NoteType, NoteTypeID, NoteTypeSchema11}, notetype::{NoteType, NoteTypeId, NoteTypeSchema11},
timestamp::TimestampMillis, timestamp::TimestampMillis,
}; };
use prost::Message; use prost::Message;
@ -41,7 +41,7 @@ fn row_to_existing_card(row: &Row) -> Result<AlreadyGeneratedCardInfo> {
} }
impl SqliteStorage { impl SqliteStorage {
pub(crate) fn get_notetype(&self, ntid: NoteTypeID) -> Result<Option<NoteType>> { pub(crate) fn get_notetype(&self, ntid: NoteTypeId) -> Result<Option<NoteType>> {
match self.get_notetype_core(ntid)? { match self.get_notetype_core(ntid)? {
Some(mut nt) => { Some(mut nt) => {
nt.fields = self.get_notetype_fields(ntid)?; nt.fields = self.get_notetype_fields(ntid)?;
@ -52,7 +52,7 @@ impl SqliteStorage {
} }
} }
fn get_notetype_core(&self, ntid: NoteTypeID) -> Result<Option<NoteType>> { fn get_notetype_core(&self, ntid: NoteTypeId) -> Result<Option<NoteType>> {
self.db self.db
.prepare_cached(concat!(include_str!("get_notetype.sql"), " where id = ?"))? .prepare_cached(concat!(include_str!("get_notetype.sql"), " where id = ?"))?
.query_and_then(&[ntid], row_to_notetype_core)? .query_and_then(&[ntid], row_to_notetype_core)?
@ -60,7 +60,7 @@ impl SqliteStorage {
.transpose() .transpose()
} }
fn get_notetype_fields(&self, ntid: NoteTypeID) -> Result<Vec<NoteField>> { fn get_notetype_fields(&self, ntid: NoteTypeId) -> Result<Vec<NoteField>> {
self.db self.db
.prepare_cached(include_str!("get_fields.sql"))? .prepare_cached(include_str!("get_fields.sql"))?
.query_and_then(&[ntid], |row| { .query_and_then(&[ntid], |row| {
@ -74,7 +74,7 @@ impl SqliteStorage {
.collect() .collect()
} }
fn get_notetype_templates(&self, ntid: NoteTypeID) -> Result<Vec<CardTemplate>> { fn get_notetype_templates(&self, ntid: NoteTypeId) -> Result<Vec<CardTemplate>> {
self.db self.db
.prepare_cached(include_str!("get_templates.sql"))? .prepare_cached(include_str!("get_templates.sql"))?
.query_and_then(&[ntid], |row| { .query_and_then(&[ntid], |row| {
@ -90,7 +90,7 @@ impl SqliteStorage {
.collect() .collect()
} }
pub(crate) fn get_notetype_id(&self, name: &str) -> Result<Option<NoteTypeID>> { pub(crate) fn get_notetype_id(&self, name: &str) -> Result<Option<NoteTypeId>> {
self.db self.db
.prepare_cached("select id from notetypes where name = ?")? .prepare_cached("select id from notetypes where name = ?")?
.query_row(params![name], |row| row.get(0)) .query_row(params![name], |row| row.get(0))
@ -98,7 +98,7 @@ impl SqliteStorage {
.map_err(Into::into) .map_err(Into::into)
} }
pub fn get_all_notetype_names(&self) -> Result<Vec<(NoteTypeID, String)>> { pub fn get_all_notetype_names(&self) -> Result<Vec<(NoteTypeId, String)>> {
self.db self.db
.prepare_cached(include_str!("get_notetype_names.sql"))? .prepare_cached(include_str!("get_notetype_names.sql"))?
.query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?)))? .query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?)))?
@ -106,7 +106,7 @@ impl SqliteStorage {
} }
/// Returns list of (id, name, use_count) /// Returns list of (id, name, use_count)
pub fn get_notetype_use_counts(&self) -> Result<Vec<(NoteTypeID, String, u32)>> { pub fn get_notetype_use_counts(&self) -> Result<Vec<(NoteTypeId, String, u32)>> {
self.db self.db
.prepare_cached(include_str!("get_use_counts.sql"))? .prepare_cached(include_str!("get_use_counts.sql"))?
.query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)))? .query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)))?
@ -115,7 +115,7 @@ impl SqliteStorage {
pub(crate) fn update_notetype_fields( pub(crate) fn update_notetype_fields(
&self, &self,
ntid: NoteTypeID, ntid: NoteTypeId,
fields: &[NoteField], fields: &[NoteField],
) -> Result<()> { ) -> Result<()> {
self.db self.db
@ -133,7 +133,7 @@ impl SqliteStorage {
/// A sorted list of all field names used by provided notes, for use with /// A sorted list of all field names used by provided notes, for use with
/// the find&replace feature. /// the find&replace feature.
pub(crate) fn field_names_for_notes(&self, nids: &[NoteID]) -> Result<Vec<String>> { pub(crate) fn field_names_for_notes(&self, nids: &[NoteId]) -> Result<Vec<String>> {
let mut sql = include_str!("field_names_for_notes.sql").to_string(); let mut sql = include_str!("field_names_for_notes.sql").to_string();
sql.push(' '); sql.push(' ');
ids_to_string(&mut sql, nids); ids_to_string(&mut sql, nids);
@ -146,8 +146,8 @@ impl SqliteStorage {
pub(crate) fn note_ids_by_notetype( pub(crate) fn note_ids_by_notetype(
&self, &self,
nids: &[NoteID], nids: &[NoteId],
) -> Result<Vec<(NoteTypeID, NoteID)>> { ) -> Result<Vec<(NoteTypeId, NoteId)>> {
let mut sql = String::from("select mid, id from notes where id in "); let mut sql = String::from("select mid, id from notes where id in ");
ids_to_string(&mut sql, nids); ids_to_string(&mut sql, nids);
sql += " order by mid, id"; sql += " order by mid, id";
@ -157,7 +157,7 @@ impl SqliteStorage {
.collect() .collect()
} }
pub(crate) fn all_note_ids_by_notetype(&self) -> Result<Vec<(NoteTypeID, NoteID)>> { pub(crate) fn all_note_ids_by_notetype(&self) -> Result<Vec<(NoteTypeId, NoteId)>> {
let sql = String::from("select mid, id from notes order by mid, id"); let sql = String::from("select mid, id from notes order by mid, id");
self.db self.db
.prepare(&sql)? .prepare(&sql)?
@ -167,7 +167,7 @@ impl SqliteStorage {
pub(crate) fn update_notetype_templates( pub(crate) fn update_notetype_templates(
&self, &self,
ntid: NoteTypeID, ntid: NoteTypeId,
templates: &[CardTemplate], templates: &[CardTemplate],
) -> Result<()> { ) -> Result<()> {
self.db self.db
@ -240,7 +240,7 @@ impl SqliteStorage {
pub(crate) fn remove_cards_for_deleted_templates( pub(crate) fn remove_cards_for_deleted_templates(
&self, &self,
ntid: NoteTypeID, ntid: NoteTypeId,
ords: &[u32], ords: &[u32],
) -> Result<()> { ) -> Result<()> {
let mut stmt = self let mut stmt = self
@ -252,7 +252,7 @@ impl SqliteStorage {
Ok(()) Ok(())
} }
pub(crate) fn remove_notetype(&self, ntid: NoteTypeID) -> Result<()> { pub(crate) fn remove_notetype(&self, ntid: NoteTypeId) -> Result<()> {
self.db self.db
.prepare_cached("delete from cards where nid in (select id from notes where mid=?)")? .prepare_cached("delete from cards where nid in (select id from notes where mid=?)")?
.execute(&[ntid])?; .execute(&[ntid])?;
@ -274,7 +274,7 @@ impl SqliteStorage {
pub(crate) fn move_cards_for_repositioned_templates( pub(crate) fn move_cards_for_repositioned_templates(
&self, &self,
ntid: NoteTypeID, ntid: NoteTypeId,
changes: &[(u32, u32)], changes: &[(u32, u32)],
) -> Result<()> { ) -> Result<()> {
let case_clauses: Vec<_> = changes let case_clauses: Vec<_> = changes
@ -297,7 +297,7 @@ and ord in ",
pub(crate) fn existing_cards_for_notetype( pub(crate) fn existing_cards_for_notetype(
&self, &self,
ntid: NoteTypeID, ntid: NoteTypeId,
) -> Result<Vec<AlreadyGeneratedCardInfo>> { ) -> Result<Vec<AlreadyGeneratedCardInfo>> {
self.db self.db
.prepare_cached(concat!( .prepare_cached(concat!(
@ -310,7 +310,7 @@ and ord in ",
pub(crate) fn existing_cards_for_note( pub(crate) fn existing_cards_for_note(
&self, &self,
nid: NoteID, nid: NoteId,
) -> Result<Vec<AlreadyGeneratedCardInfo>> { ) -> Result<Vec<AlreadyGeneratedCardInfo>> {
self.db self.db
.prepare_cached(concat!( .prepare_cached(concat!(
@ -328,7 +328,7 @@ and ord in ",
Ok(()) Ok(())
} }
pub(crate) fn highest_card_ordinal_for_notetype(&self, ntid: NoteTypeID) -> Result<u16> { pub(crate) fn highest_card_ordinal_for_notetype(&self, ntid: NoteTypeId) -> Result<u16> {
self.db self.db
.prepare(include_str!("highest_card_ord.sql"))? .prepare(include_str!("highest_card_ord.sql"))?
.query_row(&[ntid], |row| row.get(0)) .query_row(&[ntid], |row| row.get(0))
@ -339,7 +339,7 @@ and ord in ",
pub(crate) fn get_all_notetypes_as_schema11( pub(crate) fn get_all_notetypes_as_schema11(
&self, &self,
) -> Result<HashMap<NoteTypeID, NoteTypeSchema11>> { ) -> Result<HashMap<NoteTypeId, NoteTypeSchema11>> {
let mut nts = HashMap::new(); let mut nts = HashMap::new();
for (ntid, _name) in self.get_all_notetype_names()? { for (ntid, _name) in self.get_all_notetype_names()? {
let full = self.get_notetype(ntid)?.unwrap(); let full = self.get_notetype(ntid)?.unwrap();
@ -381,28 +381,28 @@ and ord in ",
self.set_schema11_notetypes(nts) self.set_schema11_notetypes(nts)
} }
fn get_schema11_notetypes(&self) -> Result<HashMap<NoteTypeID, NoteTypeSchema11>> { fn get_schema11_notetypes(&self) -> Result<HashMap<NoteTypeId, NoteTypeSchema11>> {
let mut stmt = self.db.prepare("select models from col")?; let mut stmt = self.db.prepare("select models from col")?;
let note_types = stmt let note_types = stmt
.query_and_then( .query_and_then(
NO_PARAMS, NO_PARAMS,
|row| -> Result<HashMap<NoteTypeID, NoteTypeSchema11>> { |row| -> Result<HashMap<NoteTypeId, NoteTypeSchema11>> {
let v: HashMap<NoteTypeID, NoteTypeSchema11> = let v: HashMap<NoteTypeId, NoteTypeSchema11> =
serde_json::from_str(row.get_raw(0).as_str()?)?; serde_json::from_str(row.get_raw(0).as_str()?)?;
Ok(v) Ok(v)
}, },
)? )?
.next() .next()
.ok_or_else(|| AnkiError::DBError { .ok_or_else(|| AnkiError::DbError {
info: "col table empty".to_string(), info: "col table empty".to_string(),
kind: DBErrorKind::MissingEntity, kind: DbErrorKind::MissingEntity,
})??; })??;
Ok(note_types) Ok(note_types)
} }
pub(crate) fn set_schema11_notetypes( pub(crate) fn set_schema11_notetypes(
&self, &self,
notetypes: HashMap<NoteTypeID, NoteTypeSchema11>, notetypes: HashMap<NoteTypeId, NoteTypeSchema11>,
) -> Result<()> { ) -> Result<()> {
let json = serde_json::to_string(&notetypes)?; let json = serde_json::to_string(&notetypes)?;
self.db.execute("update col set models = ?", &[json])?; self.db.execute("update col set models = ?", &[json])?;

View File

@ -64,7 +64,7 @@ impl SqliteStorage {
&self, &self,
entry: &RevlogEntry, entry: &RevlogEntry,
ensure_unique: bool, ensure_unique: bool,
) -> Result<RevlogID> { ) -> Result<RevlogId> {
self.db self.db
.prepare_cached(include_str!("add.sql"))? .prepare_cached(include_str!("add.sql"))?
.execute(params![ .execute(params![
@ -79,10 +79,10 @@ impl SqliteStorage {
entry.taken_millis, entry.taken_millis,
entry.review_kind as u8 entry.review_kind as u8
])?; ])?;
Ok(RevlogID(self.db.last_insert_rowid())) Ok(RevlogId(self.db.last_insert_rowid()))
} }
pub(crate) fn get_revlog_entry(&self, id: RevlogID) -> Result<Option<RevlogEntry>> { pub(crate) fn get_revlog_entry(&self, id: RevlogId) -> Result<Option<RevlogEntry>> {
self.db self.db
.prepare_cached(concat!(include_str!("get.sql"), " where id=?"))? .prepare_cached(concat!(include_str!("get.sql"), " where id=?"))?
.query_and_then(&[id], row_to_revlog_entry)? .query_and_then(&[id], row_to_revlog_entry)?
@ -91,14 +91,14 @@ impl SqliteStorage {
} }
/// Only intended to be used by the undo code, as Anki can not sync revlog deletions. /// Only intended to be used by the undo code, as Anki can not sync revlog deletions.
pub(crate) fn remove_revlog_entry(&self, id: RevlogID) -> Result<()> { pub(crate) fn remove_revlog_entry(&self, id: RevlogId) -> Result<()> {
self.db self.db
.prepare_cached("delete from revlog where id = ?")? .prepare_cached("delete from revlog where id = ?")?
.execute(&[id])?; .execute(&[id])?;
Ok(()) Ok(())
} }
pub(crate) fn get_revlog_entries_for_card(&self, cid: CardID) -> Result<Vec<RevlogEntry>> { pub(crate) fn get_revlog_entries_for_card(&self, cid: CardId) -> Result<Vec<RevlogEntry>> {
self.db self.db
.prepare_cached(concat!(include_str!("get.sql"), " where cid=?"))? .prepare_cached(concat!(include_str!("get.sql"), " where cid=?"))?
.query_and_then(&[cid], row_to_revlog_entry)? .query_and_then(&[cid], row_to_revlog_entry)?

View File

@ -3,7 +3,7 @@
use crate::config::schema11::schema11_config_as_string; use crate::config::schema11::schema11_config_as_string;
use crate::err::Result; use crate::err::Result;
use crate::err::{AnkiError, DBErrorKind}; use crate::err::{AnkiError, DbErrorKind};
use crate::timestamp::{TimestampMillis, TimestampSecs}; use crate::timestamp::{TimestampMillis, TimestampSecs};
use crate::{i18n::I18n, scheduler::timing::v1_creation_date, text::without_combining}; use crate::{i18n::I18n, scheduler::timing::v1_creation_date, text::without_combining};
use regex::Regex; use regex::Regex;
@ -141,17 +141,17 @@ impl SqliteStorage {
let (create, ver) = schema_version(&db)?; let (create, ver) = schema_version(&db)?;
let err = match ver { let err = match ver {
v if v < SCHEMA_MIN_VERSION => Some(DBErrorKind::FileTooOld), v if v < SCHEMA_MIN_VERSION => Some(DbErrorKind::FileTooOld),
v if v > SCHEMA_MAX_VERSION => Some(DBErrorKind::FileTooNew), v if v > SCHEMA_MAX_VERSION => Some(DbErrorKind::FileTooNew),
12 | 13 => { 12 | 13 => {
// as schema definition changed, user must perform clean // as schema definition changed, user must perform clean
// shutdown to return to schema 11 prior to running this version // shutdown to return to schema 11 prior to running this version
Some(DBErrorKind::FileTooNew) Some(DbErrorKind::FileTooNew)
} }
_ => None, _ => None,
}; };
if let Some(kind) = err { if let Some(kind) = err {
return Err(AnkiError::DBError { return Err(AnkiError::DbError {
info: "".to_string(), info: "".to_string(),
kind, kind,
}); });

View File

@ -30,7 +30,7 @@ use tempfile::NamedTempFile;
pub type FullSyncProgressFn = Box<dyn FnMut(FullSyncProgress, bool) + Send + Sync + 'static>; pub type FullSyncProgressFn = Box<dyn FnMut(FullSyncProgress, bool) + Send + Sync + 'static>;
pub struct HTTPSyncClient { pub struct HttpSyncClient {
hkey: Option<String>, hkey: Option<String>,
skey: String, skey: String,
client: Client, client: Client,
@ -62,7 +62,7 @@ impl Timeouts {
} }
#[async_trait(?Send)] #[async_trait(?Send)]
impl SyncServer for HTTPSyncClient { impl SyncServer for HttpSyncClient {
async fn meta(&self) -> Result<SyncMeta> { async fn meta(&self) -> Result<SyncMeta> {
let input = SyncRequest::Meta(MetaIn { let input = SyncRequest::Meta(MetaIn {
sync_version: SYNC_VERSION_MAX, sync_version: SYNC_VERSION_MAX,
@ -175,8 +175,8 @@ impl SyncServer for HTTPSyncClient {
} }
} }
impl HTTPSyncClient { impl HttpSyncClient {
pub fn new(hkey: Option<String>, host_number: u32) -> HTTPSyncClient { pub fn new(hkey: Option<String>, host_number: u32) -> HttpSyncClient {
let timeouts = Timeouts::new(); let timeouts = Timeouts::new();
let client = Client::builder() let client = Client::builder()
.connect_timeout(Duration::from_secs(timeouts.connect_secs)) .connect_timeout(Duration::from_secs(timeouts.connect_secs))
@ -186,7 +186,7 @@ impl HTTPSyncClient {
.unwrap(); .unwrap();
let skey = guid(); let skey = guid();
let endpoint = sync_endpoint(host_number); let endpoint = sync_endpoint(host_number);
HTTPSyncClient { HttpSyncClient {
hkey, hkey,
skey, skey,
client, client,
@ -353,7 +353,7 @@ mod test {
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
async fn http_client_inner(username: String, password: String) -> Result<()> { async fn http_client_inner(username: String, password: String) -> Result<()> {
let mut syncer = Box::new(HTTPSyncClient::new(None, 0)); let mut syncer = Box::new(HttpSyncClient::new(None, 0));
assert!(matches!( assert!(matches!(
syncer.login("nosuchuser", "nosuchpass").await, syncer.login("nosuchuser", "nosuchpass").await,
@ -420,7 +420,7 @@ mod test {
}))); })));
let out_path = syncer.full_download(None).await?; let out_path = syncer.full_download(None).await?;
let mut syncer = Box::new(HTTPSyncClient::new(None, 0)); let mut syncer = Box::new(HttpSyncClient::new(None, 0));
syncer.set_full_sync_progress_fn(Some(Box::new(|progress, _throttle| { syncer.set_full_sync_progress_fn(Some(Box::new(|progress, _throttle| {
println!("progress {:?}", progress); println!("progress {:?}", progress);
}))); })));

View File

@ -20,7 +20,7 @@ use crate::{
tags::{join_tags, split_tags, Tag}, tags::{join_tags, split_tags, Tag},
}; };
pub use http_client::FullSyncProgressFn; pub use http_client::FullSyncProgressFn;
use http_client::HTTPSyncClient; use http_client::HttpSyncClient;
pub use http_client::Timeouts; pub use http_client::Timeouts;
use itertools::Itertools; use itertools::Itertools;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -75,9 +75,9 @@ pub struct SyncMeta {
#[derive(Serialize, Deserialize, Debug, Default)] #[derive(Serialize, Deserialize, Debug, Default)]
pub struct Graves { pub struct Graves {
pub(crate) cards: Vec<CardID>, pub(crate) cards: Vec<CardId>,
pub(crate) decks: Vec<DeckID>, pub(crate) decks: Vec<DeckId>,
pub(crate) notes: Vec<NoteID>, pub(crate) notes: Vec<NoteId>,
} }
#[derive(Serialize_tuple, Deserialize, Debug, Default)] #[derive(Serialize_tuple, Deserialize, Debug, Default)]
@ -113,18 +113,18 @@ pub struct Chunk {
notes: Vec<NoteEntry>, notes: Vec<NoteEntry>,
} }
struct ChunkableIDs { struct ChunkableIds {
revlog: Vec<RevlogID>, revlog: Vec<RevlogId>,
cards: Vec<CardID>, cards: Vec<CardId>,
notes: Vec<NoteID>, notes: Vec<NoteId>,
} }
#[derive(Serialize_tuple, Deserialize, Debug)] #[derive(Serialize_tuple, Deserialize, Debug)]
pub struct NoteEntry { pub struct NoteEntry {
pub id: NoteID, pub id: NoteId,
pub guid: String, pub guid: String,
#[serde(rename = "mid")] #[serde(rename = "mid")]
pub ntid: NoteTypeID, pub ntid: NoteTypeId,
#[serde(rename = "mod")] #[serde(rename = "mod")]
pub mtime: TimestampSecs, pub mtime: TimestampSecs,
pub usn: Usn, pub usn: Usn,
@ -138,9 +138,9 @@ pub struct NoteEntry {
#[derive(Serialize_tuple, Deserialize, Debug)] #[derive(Serialize_tuple, Deserialize, Debug)]
pub struct CardEntry { pub struct CardEntry {
pub id: CardID, pub id: CardId,
pub nid: NoteID, pub nid: NoteId,
pub did: DeckID, pub did: DeckId,
pub ord: u16, pub ord: u16,
#[serde(deserialize_with = "deserialize_int_from_number")] #[serde(deserialize_with = "deserialize_int_from_number")]
pub mtime: TimestampSecs, pub mtime: TimestampSecs,
@ -157,7 +157,7 @@ pub struct CardEntry {
pub left: u32, pub left: u32,
#[serde(deserialize_with = "deserialize_int_from_number")] #[serde(deserialize_with = "deserialize_int_from_number")]
pub odue: i32, pub odue: i32,
pub odid: DeckID, pub odid: DeckId,
pub flags: u8, pub flags: u8,
pub data: String, pub data: String,
} }
@ -593,7 +593,7 @@ impl Graves {
} }
pub async fn sync_login(username: &str, password: &str) -> Result<SyncAuth> { pub async fn sync_login(username: &str, password: &str) -> Result<SyncAuth> {
let mut remote = HTTPSyncClient::new(None, 0); let mut remote = HttpSyncClient::new(None, 0);
remote.login(username, password).await?; remote.login(username, password).await?;
Ok(SyncAuth { Ok(SyncAuth {
hkey: remote.hkey().to_string(), hkey: remote.hkey().to_string(),
@ -602,12 +602,12 @@ pub async fn sync_login(username: &str, password: &str) -> Result<SyncAuth> {
} }
pub async fn sync_abort(hkey: String, host_number: u32) -> Result<()> { pub async fn sync_abort(hkey: String, host_number: u32) -> Result<()> {
let mut remote = HTTPSyncClient::new(Some(hkey), host_number); let mut remote = HttpSyncClient::new(Some(hkey), host_number);
remote.abort().await remote.abort().await
} }
pub(crate) async fn get_remote_sync_meta(auth: SyncAuth) -> Result<SyncMeta> { pub(crate) async fn get_remote_sync_meta(auth: SyncAuth) -> Result<SyncMeta> {
let remote = HTTPSyncClient::new(Some(auth.hkey), auth.host_number); let remote = HttpSyncClient::new(Some(auth.hkey), auth.host_number);
remote.meta().await remote.meta().await
} }
@ -638,7 +638,7 @@ impl Collection {
{ {
NormalSyncer::new( NormalSyncer::new(
self, self,
Box::new(HTTPSyncClient::new(Some(auth.hkey), auth.host_number)), Box::new(HttpSyncClient::new(Some(auth.hkey), auth.host_number)),
progress_fn, progress_fn,
) )
.sync() .sync()
@ -647,7 +647,7 @@ impl Collection {
/// Upload collection to AnkiWeb. Caller must re-open afterwards. /// Upload collection to AnkiWeb. Caller must re-open afterwards.
pub async fn full_upload(self, auth: SyncAuth, progress_fn: FullSyncProgressFn) -> Result<()> { pub async fn full_upload(self, auth: SyncAuth, progress_fn: FullSyncProgressFn) -> Result<()> {
let mut server = HTTPSyncClient::new(Some(auth.hkey), auth.host_number); let mut server = HttpSyncClient::new(Some(auth.hkey), auth.host_number);
server.set_full_sync_progress_fn(Some(progress_fn)); server.set_full_sync_progress_fn(Some(progress_fn));
self.full_upload_inner(Box::new(server)).await self.full_upload_inner(Box::new(server)).await
// remote.upload(&col_path, progress_fn).await?; // remote.upload(&col_path, progress_fn).await?;
@ -666,7 +666,7 @@ impl Collection {
auth: SyncAuth, auth: SyncAuth,
progress_fn: FullSyncProgressFn, progress_fn: FullSyncProgressFn,
) -> Result<()> { ) -> Result<()> {
let mut server = HTTPSyncClient::new(Some(auth.hkey), auth.host_number); let mut server = HttpSyncClient::new(Some(auth.hkey), auth.host_number);
server.set_full_sync_progress_fn(Some(progress_fn)); server.set_full_sync_progress_fn(Some(progress_fn));
self.full_download_inner(Box::new(server)).await self.full_download_inner(Box::new(server)).await
} }
@ -685,7 +685,7 @@ impl Collection {
// overwrite existing collection atomically // overwrite existing collection atomically
out_file out_file
.persist(&col_path) .persist(&col_path)
.map_err(|e| AnkiError::IOError { .map_err(|e| AnkiError::IoError {
info: format!("download save failed: {}", e), info: format!("download save failed: {}", e),
})?; })?;
Ok(()) Ok(())
@ -978,8 +978,8 @@ impl Collection {
// Local->remote chunks // Local->remote chunks
//---------------------------------------------------------------- //----------------------------------------------------------------
fn get_chunkable_ids(&self, pending_usn: Usn) -> Result<ChunkableIDs> { fn get_chunkable_ids(&self, pending_usn: Usn) -> Result<ChunkableIds> {
Ok(ChunkableIDs { Ok(ChunkableIds {
revlog: self.storage.objects_pending_sync("revlog", pending_usn)?, revlog: self.storage.objects_pending_sync("revlog", pending_usn)?,
cards: self.storage.objects_pending_sync("cards", pending_usn)?, cards: self.storage.objects_pending_sync("cards", pending_usn)?,
notes: self.storage.objects_pending_sync("notes", pending_usn)?, notes: self.storage.objects_pending_sync("notes", pending_usn)?,
@ -987,7 +987,7 @@ impl Collection {
} }
/// Fetch a chunk of ids from `ids`, returning the referenced objects. /// Fetch a chunk of ids from `ids`, returning the referenced objects.
fn get_chunk(&self, ids: &mut ChunkableIDs, new_usn: Option<Usn>) -> Result<Chunk> { fn get_chunk(&self, ids: &mut ChunkableIds, new_usn: Option<Usn>) -> Result<Chunk> {
// get a bunch of IDs // get a bunch of IDs
let mut limit = CHUNK_SIZE as i32; let mut limit = CHUNK_SIZE as i32;
let mut revlog_ids = vec![]; let mut revlog_ids = vec![];
@ -1295,9 +1295,9 @@ mod test {
} }
impl RemoteTestContext { impl RemoteTestContext {
fn server_inner(&self) -> HTTPSyncClient { fn server_inner(&self) -> HttpSyncClient {
let auth = self.auth.clone(); let auth = self.auth.clone();
HTTPSyncClient::new(Some(auth.hkey), auth.host_number) HttpSyncClient::new(Some(auth.hkey), auth.host_number)
} }
} }
@ -1327,7 +1327,7 @@ mod test {
let nt = col.get_notetype_by_name("Basic").unwrap().unwrap(); let nt = col.get_notetype_by_name("Basic").unwrap().unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
note.set_field(0, "1").unwrap(); note.set_field(0, "1").unwrap();
col.add_note(&mut note, DeckID(1)).unwrap(); col.add_note(&mut note, DeckId(1)).unwrap();
// // set our schema time back, so when initial server // // set our schema time back, so when initial server
// // col is created, it's not identical // // col is created, it's not identical
@ -1405,8 +1405,8 @@ mod test {
// mock revlog entry // mock revlog entry
col1.storage.add_revlog_entry( col1.storage.add_revlog_entry(
&RevlogEntry { &RevlogEntry {
id: RevlogID(123), id: RevlogId(123),
cid: CardID(456), cid: CardId(456),
usn: Usn(-1), usn: Usn(-1),
interval: 10, interval: 10,
..Default::default() ..Default::default()
@ -1436,7 +1436,7 @@ mod test {
let dconfid = dconf.id; let dconfid = dconf.id;
let noteid = note.id; let noteid = note.id;
let cardid = col1.search_cards(&format!("nid:{}", note.id), SortMode::NoOrder)?[0]; let cardid = col1.search_cards(&format!("nid:{}", note.id), SortMode::NoOrder)?[0];
let revlogid = RevlogID(123); let revlogid = RevlogId(123);
let compare_sides = |col1: &mut Collection, col2: &mut Collection| -> Result<()> { let compare_sides = |col1: &mut Collection, col2: &mut Collection| -> Result<()> {
assert_eq!( assert_eq!(

View File

@ -14,7 +14,7 @@ use crate::{
use async_trait::async_trait; use async_trait::async_trait;
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use super::ChunkableIDs; use super::ChunkableIds;
#[async_trait(?Send)] #[async_trait(?Send)]
pub trait SyncServer { pub trait SyncServer {
async fn meta(&self) -> Result<SyncMeta>; async fn meta(&self) -> Result<SyncMeta>;
@ -54,7 +54,7 @@ pub struct LocalServer {
/// config to client. /// config to client.
client_is_newer: bool, client_is_newer: bool,
/// Set on the first call to chunk() /// Set on the first call to chunk()
server_chunk_ids: Option<ChunkableIDs>, server_chunk_ids: Option<ChunkableIds>,
} }
impl LocalServer { impl LocalServer {

View File

@ -10,13 +10,13 @@ use super::{join_tags, split_tags};
use crate::{notes::NoteTags, prelude::*}; use crate::{notes::NoteTags, prelude::*};
impl Collection { impl Collection {
pub fn add_tags_to_notes(&mut self, nids: &[NoteID], tags: &str) -> Result<OpOutput<usize>> { pub fn add_tags_to_notes(&mut self, nids: &[NoteId], tags: &str) -> Result<OpOutput<usize>> {
self.transact(Op::UpdateTag, |col| col.add_tags_to_notes_inner(nids, tags)) self.transact(Op::UpdateTag, |col| col.add_tags_to_notes_inner(nids, tags))
} }
} }
impl Collection { impl Collection {
fn add_tags_to_notes_inner(&mut self, nids: &[NoteID], tags: &str) -> Result<usize> { fn add_tags_to_notes_inner(&mut self, nids: &[NoteId], tags: &str) -> Result<usize> {
let usn = self.usn()?; let usn = self.usn()?;
// will update tag list for any new tags, and match case // will update tag list for any new tags, and match case

View File

@ -12,7 +12,7 @@ impl Collection {
/// Replace occurences of a search with a new value in tags. /// Replace occurences of a search with a new value in tags.
pub fn find_and_replace_tag( pub fn find_and_replace_tag(
&mut self, &mut self,
nids: &[NoteID], nids: &[NoteId],
search: &str, search: &str,
replacement: &str, replacement: &str,
regex: bool, regex: bool,
@ -47,7 +47,7 @@ impl Collection {
impl Collection { impl Collection {
fn replace_tags_for_notes_inner<R: Replacer>( fn replace_tags_for_notes_inner<R: Replacer>(
&mut self, &mut self,
nids: &[NoteID], nids: &[NoteId],
regex: Regex, regex: Regex,
mut repl: R, mut repl: R,
) -> Result<usize> { ) -> Result<usize> {
@ -97,7 +97,7 @@ where
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::{collection::open_test_collection, decks::DeckID}; use crate::{collection::open_test_collection, decks::DeckId};
#[test] #[test]
fn find_replace() -> Result<()> { fn find_replace() -> Result<()> {
@ -105,7 +105,7 @@ mod test {
let nt = col.get_notetype_by_name("Basic")?.unwrap(); let nt = col.get_notetype_by_name("Basic")?.unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
note.tags.push("test".into()); note.tags.push("test".into());
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
col.find_and_replace_tag(&[note.id], "foo|test", "bar", true, false)?; col.find_and_replace_tag(&[note.id], "foo|test", "bar", true, false)?;
let note = col.storage.get_note(note.id)?.unwrap(); let note = col.storage.get_note(note.id)?.unwrap();

View File

@ -162,14 +162,14 @@ fn normalize_tag_name(name: &str) -> Cow<str> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::{collection::open_test_collection, decks::DeckID}; use crate::{collection::open_test_collection, decks::DeckId};
#[test] #[test]
fn tags() -> Result<()> { fn tags() -> Result<()> {
let mut col = open_test_collection(); let mut col = open_test_collection();
let nt = col.get_notetype_by_name("Basic")?.unwrap(); let nt = col.get_notetype_by_name("Basic")?.unwrap();
let mut note = nt.new_note(); let mut note = nt.new_note();
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
let tags: String = col.storage.db_scalar("select tags from notes")?; let tags: String = col.storage.db_scalar("select tags from notes")?;
assert_eq!(tags, ""); assert_eq!(tags, "");

View File

@ -13,7 +13,7 @@ impl Collection {
/// Remove whitespace-separated tags from provided notes. /// Remove whitespace-separated tags from provided notes.
pub fn remove_tags_from_notes( pub fn remove_tags_from_notes(
&mut self, &mut self,
nids: &[NoteID], nids: &[NoteId],
tags: &str, tags: &str,
) -> Result<OpOutput<usize>> { ) -> Result<OpOutput<usize>> {
self.transact(Op::RemoveTag, |col| { self.transact(Op::RemoveTag, |col| {
@ -54,7 +54,7 @@ impl Collection {
Ok(match_count) Ok(match_count)
} }
fn remove_tags_from_notes_inner(&mut self, nids: &[NoteID], tags: &str) -> Result<usize> { fn remove_tags_from_notes_inner(&mut self, nids: &[NoteId], tags: &str) -> Result<usize> {
let usn = self.usn()?; let usn = self.usn()?;
let mut re = TagMatcher::new(tags)?; let mut re = TagMatcher::new(tags)?;
@ -106,7 +106,7 @@ mod test {
let mut note = nt.new_note(); let mut note = nt.new_note();
note.tags.push("one".into()); note.tags.push("one".into());
note.tags.push("two".into()); note.tags.push("two".into());
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
col.set_tag_expanded("one", true)?; col.set_tag_expanded("one", true)?;
col.clear_unused_tags()?; col.clear_unused_tags()?;

View File

@ -138,7 +138,7 @@ mod test {
] { ] {
let mut note = nt.new_note(); let mut note = nt.new_note();
note.tags.push(tag.to_string()); note.tags.push(tag.to_string());
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
} }
// two decks with the same base name; they both get mapped // two decks with the same base name; they both get mapped

View File

@ -121,7 +121,7 @@ mod test {
let mut note = nt.new_note(); let mut note = nt.new_note();
note.tags.push("foo::bar::a".into()); note.tags.push("foo::bar::a".into());
note.tags.push("foo::bar::b".into()); note.tags.push("foo::bar::b".into());
col.add_note(&mut note, DeckID(1))?; col.add_note(&mut note, DeckId(1))?;
// missing parents are added // missing parents are added
assert_eq!( assert_eq!(

View File

@ -31,7 +31,7 @@ impl Trimming for Cow<'_, str> {
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum AVTag { pub enum AvTag {
SoundOrVideo(String), SoundOrVideo(String),
TextToSpeech { TextToSpeech {
field_text: String, field_text: String,
@ -179,13 +179,13 @@ pub fn strip_av_tags(text: &str) -> Cow<str> {
} }
/// Extract audio tags from string, replacing them with [anki:play] refs /// Extract audio tags from string, replacing them with [anki:play] refs
pub fn extract_av_tags(text: &str, question_side: bool) -> (Cow<str>, Vec<AVTag>) { pub fn extract_av_tags(text: &str, question_side: bool) -> (Cow<str>, Vec<AvTag>) {
let mut tags = vec![]; let mut tags = vec![];
let context = if question_side { 'q' } else { 'a' }; let context = if question_side { 'q' } else { 'a' };
let replaced_text = AV_TAGS.replace_all(text, |caps: &Captures| { let replaced_text = AV_TAGS.replace_all(text, |caps: &Captures| {
// extract // extract
let tag = if let Some(av_file) = caps.get(1) { let tag = if let Some(av_file) = caps.get(1) {
AVTag::SoundOrVideo(decode_entities(av_file.as_str()).into()) AvTag::SoundOrVideo(decode_entities(av_file.as_str()).into())
} else { } else {
let args = caps.get(2).unwrap(); let args = caps.get(2).unwrap();
let field_text = caps.get(3).unwrap(); let field_text = caps.get(3).unwrap();
@ -241,7 +241,7 @@ pub(crate) fn extract_media_refs(text: &str) -> Vec<MediaRef> {
out out
} }
fn tts_tag_from_string<'a>(field_text: &'a str, args: &'a str) -> AVTag { fn tts_tag_from_string<'a>(field_text: &'a str, args: &'a str) -> AvTag {
let mut other_args = vec![]; let mut other_args = vec![];
let mut split_args = args.split_ascii_whitespace(); let mut split_args = args.split_ascii_whitespace();
let lang = split_args.next().unwrap_or(""); let lang = split_args.next().unwrap_or("");
@ -266,7 +266,7 @@ fn tts_tag_from_string<'a>(field_text: &'a str, args: &'a str) -> AVTag {
} }
} }
AVTag::TextToSpeech { AvTag::TextToSpeech {
field_text: strip_html_for_tts(field_text).into(), field_text: strip_html_for_tts(field_text).into(),
lang: lang.into(), lang: lang.into(),
voices: voices.unwrap_or_else(Vec::new), voices: voices.unwrap_or_else(Vec::new),
@ -451,8 +451,8 @@ mod test {
assert_eq!( assert_eq!(
tags, tags,
vec![ vec![
AVTag::SoundOrVideo("fo&obar.mp3".into()), AvTag::SoundOrVideo("fo&obar.mp3".into()),
AVTag::TextToSpeech { AvTag::TextToSpeech {
field_text: "foo bar 1>2".into(), field_text: "foo bar 1>2".into(),
lang: "en_US".into(), lang: "en_US".into(),
voices: vec!["Bob".into(), "Jane".into()], voices: vec!["Bob".into(), "Jane".into()],