mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
handle some instances of floats when an integer is expected during sync
This commit is contained in:
parent
655001eaf5
commit
b363aaf401
3 changed files with 57 additions and 7 deletions
|
@ -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::serde::default_on_invalid;
|
use crate::serde::{default_on_invalid, deserialize_int_from_number};
|
||||||
use crate::{define_newtype, prelude::*};
|
use crate::{define_newtype, prelude::*};
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -20,16 +20,16 @@ pub struct RevlogEntry {
|
||||||
#[serde(rename = "ease")]
|
#[serde(rename = "ease")]
|
||||||
pub button_chosen: u8,
|
pub button_chosen: u8,
|
||||||
/// Positive values are in days, negative values in seconds.
|
/// Positive values are in days, negative values in seconds.
|
||||||
#[serde(rename = "ivl")]
|
#[serde(rename = "ivl", deserialize_with = "deserialize_int_from_number")]
|
||||||
pub interval: i32,
|
pub interval: i32,
|
||||||
/// Positive values are in days, negative values in seconds.
|
/// Positive values are in days, negative values in seconds.
|
||||||
#[serde(rename = "lastIvl")]
|
#[serde(rename = "lastIvl", deserialize_with = "deserialize_int_from_number")]
|
||||||
pub last_interval: i32,
|
pub last_interval: i32,
|
||||||
/// Card's ease after answering, stored as 10x the %, eg 2500 represents 250%.
|
/// Card's ease after answering, stored as 10x the %, eg 2500 represents 250%.
|
||||||
#[serde(rename = "factor")]
|
#[serde(rename = "factor", deserialize_with = "deserialize_int_from_number")]
|
||||||
pub ease_factor: u32,
|
pub ease_factor: u32,
|
||||||
/// Amount of milliseconds taken to answer the card.
|
/// Amount of milliseconds taken to answer the card.
|
||||||
#[serde(rename = "time")]
|
#[serde(rename = "time", deserialize_with = "deserialize_int_from_number")]
|
||||||
pub taken_millis: u32,
|
pub taken_millis: u32,
|
||||||
#[serde(rename = "type", default, deserialize_with = "default_on_invalid")]
|
#[serde(rename = "type", default, deserialize_with = "default_on_invalid")]
|
||||||
pub review_kind: RevlogReviewKind,
|
pub review_kind: RevlogReviewKind,
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// 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 serde::Deserialize as DeTrait;
|
use crate::timestamp::TimestampSecs;
|
||||||
|
use serde::{Deserialize as DeTrait, Deserializer};
|
||||||
pub(crate) use serde_aux::field_attributes::{
|
pub(crate) use serde_aux::field_attributes::{
|
||||||
deserialize_bool_from_anything, deserialize_number_from_string,
|
deserialize_bool_from_anything, deserialize_number_from_string,
|
||||||
};
|
};
|
||||||
|
@ -15,3 +16,50 @@ where
|
||||||
let v: Value = DeTrait::deserialize(deserializer)?;
|
let v: Value = DeTrait::deserialize(deserializer)?;
|
||||||
Ok(T::deserialize(v).unwrap_or_default())
|
Ok(T::deserialize(v).unwrap_or_default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_int_from_number<'de, T, D>(deserializer: D) -> Result<T, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
T: serde::Deserialize<'de> + FromF64,
|
||||||
|
{
|
||||||
|
#[derive(DeTrait)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum IntOrFloat<T> {
|
||||||
|
Int(T),
|
||||||
|
Float(f64),
|
||||||
|
}
|
||||||
|
|
||||||
|
match IntOrFloat::<T>::deserialize(deserializer)? {
|
||||||
|
IntOrFloat::Float(s) => Ok(T::from_f64(s)),
|
||||||
|
IntOrFloat::Int(i) => Ok(i),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It may be possible to use the num_traits crate instead in the future.
|
||||||
|
pub trait FromF64 {
|
||||||
|
fn from_f64(val: f64) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromF64 for i32 {
|
||||||
|
fn from_f64(val: f64) -> Self {
|
||||||
|
val as Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromF64 for u32 {
|
||||||
|
fn from_f64(val: f64) -> Self {
|
||||||
|
val as Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromF64 for i64 {
|
||||||
|
fn from_f64(val: f64) -> Self {
|
||||||
|
val as Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromF64 for TimestampSecs {
|
||||||
|
fn from_f64(val: f64) -> Self {
|
||||||
|
TimestampSecs(val as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
||||||
notetype::{NoteType, NoteTypeSchema11},
|
notetype::{NoteType, NoteTypeSchema11},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
revlog::RevlogEntry,
|
revlog::RevlogEntry,
|
||||||
serde::default_on_invalid,
|
serde::{default_on_invalid, deserialize_int_from_number},
|
||||||
tags::{join_tags, split_tags},
|
tags::{join_tags, split_tags},
|
||||||
version::sync_client_version,
|
version::sync_client_version,
|
||||||
};
|
};
|
||||||
|
@ -139,11 +139,13 @@ pub struct CardEntry {
|
||||||
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")]
|
||||||
pub mtime: TimestampSecs,
|
pub mtime: TimestampSecs,
|
||||||
pub usn: Usn,
|
pub usn: Usn,
|
||||||
pub ctype: CardType,
|
pub ctype: CardType,
|
||||||
pub queue: CardQueue,
|
pub queue: CardQueue,
|
||||||
pub due: i32,
|
pub due: i32,
|
||||||
|
#[serde(deserialize_with = "deserialize_int_from_number")]
|
||||||
pub ivl: u32,
|
pub ivl: u32,
|
||||||
pub factor: u16,
|
pub factor: u16,
|
||||||
pub reps: u32,
|
pub reps: u32,
|
||||||
|
|
Loading…
Reference in a new issue