mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-10-09 23:26:31 +00:00
copy on wasm side to avoid any data corruption
This commit is contained in:
1 parent
b843a18441
commit
adbe4a2693
2 files changed
+30
-39
No files matched your search
+10
-19
@@ -114,8 +114,7 @@ pub fn start() {
|
|||||||
|
|
||||||
// Statistics buffers
|
// Statistics buffers
|
||||||
//
|
//
|
||||||
// These are views into wasm memory: they are invalidated by the next command (and any
|
// Each getter returns a copy of the buffer, as a new JS typed array.
|
||||||
// allocation), so read or copy them right away.
|
|
||||||
|
|
||||||
fn with_stats<T>(f: impl FnOnce(&engine::StatisticsBuffer) -> T) -> Option<T> {
|
fn with_stats<T>(f: impl FnOnce(&engine::StatisticsBuffer) -> T) -> Option<T> {
|
||||||
ENGINE.with(|engine| engine.borrow().as_ref().map(|e| f(e.statistics())))
|
ENGINE.with(|engine| engine.borrow().as_ref().map(|e| f(e.statistics())))
|
||||||
@@ -125,8 +124,7 @@ macro_rules! stats_getter {
|
|||||||
($name:ident, $array:ident) => {
|
($name:ident, $array:ident) => {
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn $name() -> $array {
|
pub fn $name() -> $array {
|
||||||
with_stats(|s| unsafe { $array::view(&s.$name) })
|
with_stats(|s| $array::from(&s.$name[..])).unwrap_or_else(|| $array::new_with_length(0))
|
||||||
.unwrap_or_else(|| $array::new_with_length(0))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -152,12 +150,7 @@ macro_rules! optional_stats_getter {
|
|||||||
($name:ident, $field:ident, $array:ident) => {
|
($name:ident, $field:ident, $array:ident) => {
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn $name() -> Option<$array> {
|
pub fn $name() -> Option<$array> {
|
||||||
with_stats(|s| {
|
with_stats(|s| s.$field.as_deref().map($array::from)).flatten()
|
||||||
s.$field
|
|
||||||
.as_ref()
|
|
||||||
.map(|values| unsafe { $array::view(values) })
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -185,13 +178,13 @@ macro_rules! intervals_getters {
|
|||||||
($starts:ident, $values:ident, $field:ident) => {
|
($starts:ident, $values:ident, $field:ident) => {
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn $starts() -> Uint32Array {
|
pub fn $starts() -> Uint32Array {
|
||||||
with_stats(|s| unsafe { Uint32Array::view(&s.$field.starts) })
|
with_stats(|s| Uint32Array::from(&s.$field.starts[..]))
|
||||||
.unwrap_or_else(|| Uint32Array::new_with_length(0))
|
.unwrap_or_else(|| Uint32Array::new_with_length(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn $values() -> Uint8Array {
|
pub fn $values() -> Uint8Array {
|
||||||
with_stats(|s| unsafe { Uint8Array::view(&s.$field.values) })
|
with_stats(|s| Uint8Array::from(&s.$field.values[..]))
|
||||||
.unwrap_or_else(|| Uint8Array::new_with_length(0))
|
.unwrap_or_else(|| Uint8Array::new_with_length(0))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1214,14 +1207,12 @@ pub fn last_update() -> FilesUpdate {
|
|||||||
|
|
||||||
// Coordinates buffers
|
// Coordinates buffers
|
||||||
//
|
//
|
||||||
// Like the statistics buffers, these are views into wasm memory, invalidated by the next
|
// Like the statistics buffers, these are copies. They are flat `[lng, lat, ...]` arrays. Compare `rev` / `waypointsRev` of the file structures with the previous ones to know which
|
||||||
// command (and any allocation): read or copy them right away. They are flat `[lng, lat, ...]`
|
|
||||||
// arrays. Compare `rev` / `waypointsRev` of the file structures with the previous ones to know which
|
|
||||||
// buffers actually changed.
|
// buffers actually changed.
|
||||||
|
|
||||||
fn coordinates_view(f: impl FnOnce(&Engine) -> Option<&[f64]>) -> Float64Array {
|
fn coordinates_array(f: impl FnOnce(&Engine) -> Option<&[f64]>) -> Float64Array {
|
||||||
ENGINE.with(|engine| match engine.borrow().as_ref().and_then(f) {
|
ENGINE.with(|engine| match engine.borrow().as_ref().and_then(f) {
|
||||||
Some(coordinates) => unsafe { Float64Array::view(coordinates) },
|
Some(coordinates) => Float64Array::from(coordinates),
|
||||||
None => Float64Array::new_with_length(0),
|
None => Float64Array::new_with_length(0),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1230,7 +1221,7 @@ fn coordinates_view(f: impl FnOnce(&Engine) -> Option<&[f64]>) -> Float64Array {
|
|||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn segment_coordinates(segment_id: &str) -> Float64Array {
|
pub fn segment_coordinates(segment_id: &str) -> Float64Array {
|
||||||
match uuid::Uuid::parse_str(segment_id) {
|
match uuid::Uuid::parse_str(segment_id) {
|
||||||
Ok(id) => coordinates_view(|e| Some(e.segment_coordinates(&engine::TrackSegmentId(id)))),
|
Ok(id) => coordinates_array(|e| Some(e.segment_coordinates(&engine::TrackSegmentId(id)))),
|
||||||
Err(_) => Float64Array::new_with_length(0),
|
Err(_) => Float64Array::new_with_length(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1239,7 +1230,7 @@ pub fn segment_coordinates(segment_id: &str) -> Float64Array {
|
|||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn waypoint_coordinates(file_id: &str) -> Float64Array {
|
pub fn waypoint_coordinates(file_id: &str) -> Float64Array {
|
||||||
match uuid::Uuid::parse_str(file_id) {
|
match uuid::Uuid::parse_str(file_id) {
|
||||||
Ok(id) => coordinates_view(|e| Some(e.waypoint_coordinates(&FileId(id)))),
|
Ok(id) => coordinates_array(|e| Some(e.waypoint_coordinates(&FileId(id)))),
|
||||||
Err(_) => Float64Array::new_with_length(0),
|
Err(_) => Float64Array::new_with_length(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+20
-20
@@ -566,15 +566,15 @@ class Engine {
|
|||||||
store.update((state) => ({ ...state, visibility }));
|
store.update((state) => ({ ...state, visibility }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coordinates, as flat [lng, lat, ...] arrays. They are copied out of the WASM memory.
|
// Coordinates, as flat [lng, lat, ...] arrays. The getters copy them out of the WASM memory.
|
||||||
// Refetch them when the `rev` of the segment (or the `waypointsRev` of the file) changed.
|
// Refetch them when the `rev` of the segment (or the `waypointsRev` of the file) changed.
|
||||||
|
|
||||||
segmentCoordinates(segmentId: string): Float64Array {
|
segmentCoordinates(segmentId: string): Float64Array {
|
||||||
return this.wasm?.segment_coordinates(segmentId).slice() ?? new Float64Array();
|
return this.wasm?.segment_coordinates(segmentId) ?? new Float64Array();
|
||||||
}
|
}
|
||||||
|
|
||||||
waypointCoordinates(fileId: string): Float64Array {
|
waypointCoordinates(fileId: string): Float64Array {
|
||||||
return this.wasm?.waypoint_coordinates(fileId).slice() ?? new Float64Array();
|
return this.wasm?.waypoint_coordinates(fileId) ?? new Float64Array();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async run(action: (wasm: Wasm) => boolean): Promise<boolean> {
|
private async run(action: (wasm: Wasm) => boolean): Promise<boolean> {
|
||||||
@@ -640,22 +640,22 @@ class Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies the statistics buffers of the engine (they are overwritten by the next action), but
|
* Reads the statistics buffers of the engine (the getters copy them), but only the metrics
|
||||||
* only the metrics that were requested.
|
* that were requested.
|
||||||
*/
|
*/
|
||||||
private readStatistics(wasm: Wasm): SelectionStatistics {
|
private readStatistics(wasm: Wasm): SelectionStatistics {
|
||||||
const version = ++this._statisticsVersion;
|
const version = ++this._statisticsVersion;
|
||||||
this._loadedMetrics.clear();
|
this._loadedMetrics.clear();
|
||||||
const totalDistance = wasm.total_distance().slice();
|
const totalDistance = wasm.total_distance();
|
||||||
const statistics: SelectionStatistics = {
|
const statistics: SelectionStatistics = {
|
||||||
global: wasm.selection_statistics() ?? EMPTY_STATISTICS,
|
global: wasm.selection_statistics() ?? EMPTY_STATISTICS,
|
||||||
length: totalDistance.length,
|
length: totalDistance.length,
|
||||||
totalDistance,
|
totalDistance,
|
||||||
slope: wasm.slope().slice(),
|
slope: wasm.slope(),
|
||||||
lng: wasm.lng().slice(),
|
lng: wasm.lng(),
|
||||||
lat: wasm.lat().slice(),
|
lat: wasm.lat(),
|
||||||
ele: wasm.ele().slice(),
|
ele: wasm.ele(),
|
||||||
timestamps: wasm.timestamps()?.slice(),
|
timestamps: wasm.timestamps(),
|
||||||
slice: (start, end) =>
|
slice: (start, end) =>
|
||||||
version === this._statisticsVersion ? wasm.slice_statistics(start, end) : undefined,
|
version === this._statisticsVersion ? wasm.slice_statistics(start, end) : undefined,
|
||||||
};
|
};
|
||||||
@@ -680,8 +680,8 @@ class Engine {
|
|||||||
values: Uint8Array,
|
values: Uint8Array,
|
||||||
names: () => string[]
|
names: () => string[]
|
||||||
): CategoryIntervals => ({
|
): CategoryIntervals => ({
|
||||||
starts: starts.slice(),
|
starts,
|
||||||
values: values.slice(),
|
values,
|
||||||
names: names(),
|
names: names(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -692,23 +692,23 @@ class Engine {
|
|||||||
this._loadedMetrics.add(metric);
|
this._loadedMetrics.add(metric);
|
||||||
switch (metric) {
|
switch (metric) {
|
||||||
case 'speed':
|
case 'speed':
|
||||||
statistics.speed = wasm.speed().slice();
|
statistics.speed = wasm.speed();
|
||||||
break;
|
break;
|
||||||
case 'hr':
|
case 'hr':
|
||||||
statistics.hr = wasm.hr()?.slice();
|
statistics.hr = wasm.hr();
|
||||||
break;
|
break;
|
||||||
case 'cad':
|
case 'cad':
|
||||||
statistics.cad = wasm.cad()?.slice();
|
statistics.cad = wasm.cad();
|
||||||
break;
|
break;
|
||||||
case 'atemp':
|
case 'atemp':
|
||||||
statistics.atemp = wasm.atemp()?.slice();
|
statistics.atemp = wasm.atemp();
|
||||||
break;
|
break;
|
||||||
case 'power':
|
case 'power':
|
||||||
statistics.power = wasm.power()?.slice();
|
statistics.power = wasm.power();
|
||||||
break;
|
break;
|
||||||
case 'slopeSegment':
|
case 'slopeSegment':
|
||||||
statistics.slopeSegmentSlope = wasm.slope_segment_slope().slice();
|
statistics.slopeSegmentSlope = wasm.slope_segment_slope();
|
||||||
statistics.slopeSegmentDistance = wasm.slope_segment_distance().slice();
|
statistics.slopeSegmentDistance = wasm.slope_segment_distance();
|
||||||
break;
|
break;
|
||||||
case 'surface':
|
case 'surface':
|
||||||
statistics.surface = categories(
|
statistics.surface = categories(
|
||||||
|
|||||||
Reference in new issue
Block a user