cleanup + properly handle saving function data
This commit is contained in:
parent
24526d138d
commit
123c49a5d8
@ -11,6 +11,7 @@ use parsing::{process_func_str, BackingFunction};
|
||||
use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::{
|
||||
fmt::{self, Debug},
|
||||
hash::{Hash, Hasher},
|
||||
intrinsics::assume,
|
||||
};
|
||||
|
||||
@ -62,6 +63,16 @@ pub struct FunctionEntry {
|
||||
pub settings_opened: bool,
|
||||
}
|
||||
|
||||
impl Hash for FunctionEntry {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.raw_func_str.hash(state);
|
||||
self.integral.hash(state);
|
||||
self.nth_derviative.hash(state);
|
||||
self.curr_nth.hash(state);
|
||||
self.settings_opened.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for FunctionEntry {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
|
||||
@ -9,6 +9,9 @@ use serde::Deserialize;
|
||||
use serde::Deserializer;
|
||||
use serde::Serialize;
|
||||
use serde::Serializer;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::ops::BitXorAssign;
|
||||
|
||||
pub struct FunctionManager {
|
||||
@ -19,7 +22,7 @@ impl Default for FunctionManager {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
functions: vec![(
|
||||
Id::new_from_u64(11414819524356497634), // Random number here to avoid call to random
|
||||
Id::new_from_u64(11414819524356497634), // Random number here to avoid call to crate::misc::random_u64()
|
||||
FunctionEntry::EMPTY,
|
||||
)],
|
||||
}
|
||||
@ -72,7 +75,17 @@ const fn button_area_button(text: impl Into<WidgetText>) -> Button {
|
||||
}
|
||||
|
||||
impl FunctionManager {
|
||||
pub fn display_entries(&mut self, ui: &mut egui::Ui) {
|
||||
#[inline]
|
||||
fn get_hash(&self) -> u64 {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
self.functions.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
}
|
||||
|
||||
/// Displays function entries alongside returning whether or not functions have been modified
|
||||
pub fn display_entries(&mut self, ui: &mut egui::Ui) -> bool {
|
||||
let initial_hash = self.get_hash();
|
||||
|
||||
let can_remove = self.functions.len() > 1;
|
||||
|
||||
let available_width = ui.available_width();
|
||||
@ -127,6 +140,8 @@ impl FunctionManager {
|
||||
|
||||
if movement != Movement::Complete && let Some(hints) = function.autocomplete.hint.many() {
|
||||
// Doesn't need to have a number in id as there should only be 1 autocomplete popup in the entire gui
|
||||
|
||||
// hashed "autocomplete_popup"
|
||||
const POPUP_ID: Id = Id::new_from_u64(7574801616484505465);
|
||||
|
||||
let mut clicked = false;
|
||||
@ -217,6 +232,10 @@ impl FunctionManager {
|
||||
if let Some(remove_i_unwrap) = remove_i {
|
||||
self.functions.remove(remove_i_unwrap);
|
||||
}
|
||||
|
||||
let final_hash = self.get_hash();
|
||||
|
||||
initial_hash != final_hash
|
||||
}
|
||||
|
||||
/// Create and push new empty function entry
|
||||
|
||||
@ -386,7 +386,23 @@ impl MathApp {
|
||||
);
|
||||
});
|
||||
|
||||
self.functions.display_entries(ui);
|
||||
if self.functions.display_entries(ui) {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
tracing::info!("Saving function data");
|
||||
let hash: crate::misc::HashBytes = unsafe {
|
||||
std::mem::transmute::<&str, crate::misc::HashBytes>(build::SHORT_COMMIT)
|
||||
};
|
||||
let saved_data = &crate::misc::hashed_storage_create(
|
||||
hash,
|
||||
bincode::serialize(&self.functions).unwrap().as_slice(),
|
||||
);
|
||||
// tracing::info!("Bytes: {}", saved_data.len());
|
||||
get_localstorage()
|
||||
.set_item(FUNC_NAME, saved_data)
|
||||
.expect("failed to set local function storage");
|
||||
}
|
||||
}
|
||||
|
||||
// Only render if there's enough space
|
||||
if ui.available_height() > crate::data::FONT_SIZE {
|
||||
@ -633,31 +649,7 @@ impl App for MathApp {
|
||||
self.last_info.1 = start.map(|a| format!("Took: {:?}", a.elapsed()));
|
||||
}
|
||||
|
||||
fn save(&mut self, _: &mut dyn eframe::Storage) {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
self.save_functions();
|
||||
}
|
||||
|
||||
fn auto_save_interval(&self) -> std::time::Duration { std::time::Duration::from_secs(10) }
|
||||
|
||||
fn clear_color(&self, _visuals: &egui::Visuals) -> egui::Rgba {
|
||||
crate::style::STYLE.window_fill().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl MathApp {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn save_functions(&self) {
|
||||
tracing::info!("Saving function data");
|
||||
let hash: crate::misc::HashBytes =
|
||||
unsafe { std::mem::transmute::<&str, crate::misc::HashBytes>(build::SHORT_COMMIT) };
|
||||
let saved_data = &crate::misc::hashed_storage_create(
|
||||
hash,
|
||||
bincode::serialize(&self.functions).unwrap().as_slice(),
|
||||
);
|
||||
// tracing::info!("Bytes: {}", saved_data.len());
|
||||
get_localstorage()
|
||||
.set_item(FUNC_NAME, saved_data)
|
||||
.expect("failed to set local function storage");
|
||||
}
|
||||
}
|
||||
|
||||
14
src/misc.rs
14
src/misc.rs
@ -1,5 +1,3 @@
|
||||
use std::intrinsics::assume;
|
||||
|
||||
use egui::plot::{Line, Points, Value, Values};
|
||||
use getrandom::getrandom;
|
||||
use itertools::Itertools;
|
||||
@ -163,25 +161,27 @@ pub fn hashed_storage_create(hash: HashBytes, data: &[u8]) -> String {
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const fn hashed_storage_read(data: &str) -> Option<(HashBytes, &[u8])> {
|
||||
// Make sure data is long enough to decode
|
||||
if HASH_LENGTH >= data.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
assume(!data.is_empty());
|
||||
assume(data.len() > HASH_LENGTH);
|
||||
}
|
||||
|
||||
// Transmute data into slice
|
||||
let decoded_1: &[u8] = unsafe { std::mem::transmute::<&str, &[u8]>(data) };
|
||||
|
||||
// return hash and decoded data
|
||||
Some((
|
||||
unsafe { *(decoded_1[..HASH_LENGTH].as_ptr() as *const HashBytes) },
|
||||
&decoded_1[HASH_LENGTH..],
|
||||
))
|
||||
}
|
||||
|
||||
/// Creates and returns random u64
|
||||
pub fn random_u64() -> Result<u64, getrandom::Error> {
|
||||
// Buffer of 8 `u8`s that are later merged into one u64
|
||||
let mut buf = [0u8; 8];
|
||||
// Populate buffer with random values
|
||||
getrandom(&mut buf)?;
|
||||
// Merge buffer into u64
|
||||
Ok(u64::from_be_bytes(buf))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user