wasm first steps

This commit is contained in:
vcoppe committed 2026-07-14 18:36:30 +02:00
1 parent 86f4fc3394
commit ed6264444f
11 files changed
+398 -3

No files matched your search

+27
View File
@@ -0,0 +1,27 @@
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use crate::{stack::Stack, types::GPXFile};
#[wasm_bindgen]
pub struct Controller {
stack: Stack,
}
#[wasm_bindgen]
impl Controller {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self {
stack: Stack::default(),
}
}
#[wasm_bindgen]
pub fn create_file(&mut self, name: &str) {
let id = self.stack.get_new_file_id();
let file = Rc::new(GPXFile::new(id, name));
self.stack.update(&[file]);
}
}
+3
View File
@@ -0,0 +1,3 @@
mod controller;
mod stack;
mod types;
+101
View File
@@ -0,0 +1,101 @@
use std::{collections::HashMap, rc::Rc};
use crate::types::{GPXFile, GPXFileId};
#[derive(Default)]
pub struct Stack {
entries: Vec<StackEntry>,
index: Option<usize>,
}
impl Stack {
pub fn current(&self) -> Option<&StackEntry> {
match self.index {
Some(i) => Some(&self.entries[i]),
None => None,
}
}
pub fn get_new_file_id(&self) -> GPXFileId {
if let Some(current) = self.current() {
for id in 0..current.len() {
if !current.contains_key(&id) {
return id;
}
}
current.len() as GPXFileId
} else {
0
}
}
pub fn update(&mut self, files: &[Rc<GPXFile>]) {
let mut next = match self.current() {
Some(current) => current.clone(),
None => StackEntry::default(),
};
for file in files {
next.insert(file.id, file.clone());
}
self.push(next);
}
pub fn delete(&mut self, files: &[GPXFileId]) {
if let Some(current) = self.current() {
let mut next = current.clone();
for file in files {
next.remove(file);
}
self.push(next);
}
}
pub fn can_undo(&self) -> bool {
self.index.is_some()
}
pub fn can_redo(&self) -> bool {
match self.index {
Some(i) => i + 1 < self.entries.len(),
None => !self.entries.is_empty(),
}
}
pub fn undo(&mut self) {
if let Some(i) = self.index {
if i == 0 {
self.index = None;
} else {
self.index = Some(i - 1);
}
}
}
pub fn redo(&mut self) {
match self.index {
Some(i) => {
if i + 1 < self.entries.len() {
self.index = Some(i + 1);
}
}
None => {
if !self.entries.is_empty() {
self.index = Some(0);
}
}
}
}
fn push(&mut self, entry: StackEntry) {
if let Some(i) = self.index {
if i + 1 < self.entries.len() {
self.entries.truncate(i + 1);
}
}
self.entries.push(entry);
self.index = Some(self.entries.len() - 1);
}
}
pub type StackEntry = HashMap<GPXFileId, Rc<GPXFile>>;
+106
View File
@@ -0,0 +1,106 @@
use std::rc::Rc;
pub type GPXFileId = usize;
pub struct GPXFile {
pub id: GPXFileId,
pub info: Rc<GPXFileInfo>,
pub trk: Vec<Track>,
pub wpt: Vec<Rc<WaypointChunk>>,
}
impl GPXFile {
pub fn new(id: GPXFileId, name: &str) -> Self {
Self {
id,
info: Rc::new(GPXFileInfo::new(name)),
trk: Vec::new(),
wpt: Vec::new(),
}
}
}
pub struct GPXFileInfo {
pub name: String,
pub desc: Option<String>,
pub author: Option<Author>,
pub link: Option<Link>,
pub time: Option<i64>,
}
impl GPXFileInfo {
pub fn new(name: &str) -> Self {
Self {
name: name.to_owned(),
desc: None,
author: None,
link: None,
time: None,
}
}
}
pub struct Author {
pub name: Option<String>,
pub email: Option<String>,
pub link: Option<Link>,
}
pub struct Link {
pub href: String,
pub text: Option<String>,
pub type_: Option<String>,
}
pub struct Track {
pub info: Rc<TrackInfo>,
pub trkseg: Vec<TrackSegment>,
}
pub struct TrackInfo {
name: Option<String>,
cmt: Option<String>,
desc: Option<String>,
src: Option<String>,
link: Option<Link>,
type_: Option<String>,
color: Option<String>,
opacity: Option<f64>,
width: Option<f64>,
}
pub struct TrackSegment {
pub trkpt: Vec<Rc<TrackPointChunk>>,
}
pub type TrackPointChunk = Vec<TrackPoint>;
pub struct TrackPoint {
pub coordinates: LngLat,
pub ele: f64,
pub time: Option<i64>,
pub hr: Option<u16>,
pub cad: Option<u16>,
pub power: Option<u16>,
pub atemp: Option<i16>,
// TODO OSM data? or store intervals at a higher level?
}
pub type WaypointChunk = Vec<Waypoint>;
pub struct Waypoint {
pub coordinates: LngLat,
pub ele: f64,
pub time: Option<i64>,
pub name: Option<String>,
pub cmt: Option<String>,
pub desc: Option<String>,
pub link: Option<Link>,
pub sym: Option<String>,
pub type_: Option<String>,
}
pub struct LngLat {
pub lng: f64,
pub lat: f64,
}