mirror of
https://github.com/ankitects/anki.git
synced 2025-11-15 00:57:13 -05:00
Avoid excessive floating point precision when serializing
This commit is contained in:
parent
03edb7bf9e
commit
8b849dd629
2 changed files with 38 additions and 15 deletions
|
|
@ -5,9 +5,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use rusqlite::types::FromSql;
|
use rusqlite::types::FromSql;
|
||||||
use rusqlite::types::FromSqlError;
|
use rusqlite::types::FromSqlError;
|
||||||
use rusqlite::types::ToSqlOutput;
|
|
||||||
use rusqlite::types::ValueRef;
|
use rusqlite::types::ValueRef;
|
||||||
use rusqlite::ToSql;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
@ -78,6 +76,24 @@ impl CardData {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn convert_to_json(&mut self) -> Result<String> {
|
||||||
|
if let Some(v) = &mut self.fsrs_stability {
|
||||||
|
round_to_places(v, 1)
|
||||||
|
}
|
||||||
|
if let Some(v) = &mut self.fsrs_difficulty {
|
||||||
|
round_to_places(v, 3)
|
||||||
|
}
|
||||||
|
if let Some(v) = &mut self.fsrs_desired_retention {
|
||||||
|
round_to_places(v, 2)
|
||||||
|
}
|
||||||
|
serde_json::to_string(&self).map_err(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn round_to_places(value: &mut f32, decimal_places: u32) {
|
||||||
|
let factor = 10_f32.powi(decimal_places as i32);
|
||||||
|
*value = (*value * factor).round() / factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromSql for CardData {
|
impl FromSql for CardData {
|
||||||
|
|
@ -91,17 +107,9 @@ impl FromSql for CardData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToSql for CardData {
|
|
||||||
fn to_sql(&self) -> Result<ToSqlOutput<'_>, rusqlite::Error> {
|
|
||||||
Ok(ToSqlOutput::Owned(
|
|
||||||
serde_json::to_string(self).unwrap().into(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize the JSON `data` for a card.
|
/// Serialize the JSON `data` for a card.
|
||||||
pub(crate) fn card_data_string(card: &Card) -> String {
|
pub(crate) fn card_data_string(card: &Card) -> String {
|
||||||
serde_json::to_string(&CardData::from_card(card)).unwrap()
|
CardData::from_card(card).convert_to_json().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta_is_empty(s: &str) -> bool {
|
fn meta_is_empty(s: &str) -> bool {
|
||||||
|
|
@ -143,4 +151,19 @@ mod test {
|
||||||
assert!(validate_custom_data(r#"{"日本語": 5}"#).is_err());
|
assert!(validate_custom_data(r#"{"日本語": 5}"#).is_err());
|
||||||
assert!(validate_custom_data(&format!(r#"{{"foo": "{}"}}"#, "x".repeat(100))).is_err());
|
assert!(validate_custom_data(&format!(r#"{{"foo": "{}"}}"#, "x".repeat(100))).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compact_floats() {
|
||||||
|
let mut data = CardData {
|
||||||
|
original_position: None,
|
||||||
|
fsrs_stability: Some(123.45678),
|
||||||
|
fsrs_difficulty: Some(1.234567),
|
||||||
|
fsrs_desired_retention: Some(0.987654),
|
||||||
|
custom_data: "".to_string(),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
data.convert_to_json().unwrap(),
|
||||||
|
r#"{"s":123.5,"d":1.235,"dr":0.99}"#
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ impl super::SqliteStorage {
|
||||||
card.original_due,
|
card.original_due,
|
||||||
card.original_deck_id,
|
card.original_deck_id,
|
||||||
card.flags,
|
card.flags,
|
||||||
CardData::from_card(card),
|
CardData::from_card(card).convert_to_json()?,
|
||||||
card.id,
|
card.id,
|
||||||
])?;
|
])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -153,7 +153,7 @@ impl super::SqliteStorage {
|
||||||
card.original_due,
|
card.original_due,
|
||||||
card.original_deck_id,
|
card.original_deck_id,
|
||||||
card.flags,
|
card.flags,
|
||||||
CardData::from_card(card),
|
CardData::from_card(card).convert_to_json()?,
|
||||||
])?;
|
])?;
|
||||||
card.id = CardId(self.db.last_insert_rowid());
|
card.id = CardId(self.db.last_insert_rowid());
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -181,7 +181,7 @@ impl super::SqliteStorage {
|
||||||
card.original_due,
|
card.original_due,
|
||||||
card.original_deck_id,
|
card.original_deck_id,
|
||||||
card.flags,
|
card.flags,
|
||||||
CardData::from_card(card),
|
CardData::from_card(card).convert_to_json()?,
|
||||||
])
|
])
|
||||||
.map(|n_rows| n_rows == 1)
|
.map(|n_rows| n_rows == 1)
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
|
|
@ -208,7 +208,7 @@ impl super::SqliteStorage {
|
||||||
card.original_due,
|
card.original_due,
|
||||||
card.original_deck_id,
|
card.original_deck_id,
|
||||||
card.flags,
|
card.flags,
|
||||||
CardData::from_card(card),
|
CardData::from_card(card).convert_to_json()?,
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue