Compare commits
No commits in common. "main" and "0.2.0" have entirely different histories.
3
Makefile
3
Makefile
@ -25,8 +25,7 @@ check:
|
||||
cargo deny check
|
||||
|
||||
serve: wasm
|
||||
cd woweb; \
|
||||
cargo run
|
||||
cargo run --package woweb
|
||||
|
||||
release: $(DIST_DIR) wasm
|
||||
cargo build --package woweb --release
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crdts::list::Op;
|
||||
use crdts::{CmRDT, List};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use crdts::{CmRDT, List};
|
||||
use crdts::list::Op;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Text {
|
||||
@ -9,7 +9,9 @@ pub struct Text {
|
||||
|
||||
impl Default for Text {
|
||||
fn default() -> Self {
|
||||
Self { inner: List::new() }
|
||||
Self {
|
||||
inner: List::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,26 +25,14 @@ impl Display for Text {
|
||||
|
||||
impl Text {
|
||||
pub fn apply_ops(&mut self, ops: Vec<Op<u16, String>>) {
|
||||
ops.iter()
|
||||
.for_each(move |op| self.inner.apply(op.to_owned()));
|
||||
ops.iter().for_each(move |op| self.inner.apply(op.to_owned()));
|
||||
}
|
||||
|
||||
pub fn insert_linebreak(
|
||||
&mut self,
|
||||
start: usize,
|
||||
end: usize,
|
||||
src: &str,
|
||||
) -> Vec<Op<u16, String>> {
|
||||
pub fn insert_linebreak(&mut self, start: usize, end: usize, src: &str) -> Vec<Op<u16, String>> {
|
||||
self.insert(start, end, "\n", src)
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
&mut self,
|
||||
start: usize,
|
||||
end: usize,
|
||||
data: &str,
|
||||
src: &str,
|
||||
) -> Vec<Op<u16, String>> {
|
||||
pub fn insert(&mut self, start: usize, end: usize, data: &str, src: &str) -> Vec<Op<u16, String>> {
|
||||
let mut ops: Vec<Op<u16, String>> = Vec::new();
|
||||
|
||||
if start < end {
|
||||
@ -65,22 +55,14 @@ impl Text {
|
||||
}
|
||||
|
||||
pub fn delete_backward(&mut self, start: usize, end: usize, src: &str) -> Vec<Op<u16, String>> {
|
||||
if (start == 0 && start == end) || end > self.inner.len() {
|
||||
return Vec::new();
|
||||
}
|
||||
if (start == 0 && start == end) || end > self.inner.len() { return Vec::new(); }
|
||||
|
||||
let (end, start) = if start == end {
|
||||
(start, start - 1)
|
||||
} else {
|
||||
(end, start)
|
||||
};
|
||||
let (end, start) = if start == end { (start, start - 1) } else { (end, start) };
|
||||
self.delete(start, end, src)
|
||||
}
|
||||
|
||||
pub fn delete_forward(&mut self, start: usize, end: usize, src: &str) -> Vec<Op<u16, String>> {
|
||||
if start >= self.inner.len() {
|
||||
return Vec::new();
|
||||
}
|
||||
if start >= self.inner.len() { return Vec::new(); }
|
||||
|
||||
let end = if start == end { start + 1 } else { end };
|
||||
self.delete(start, end, src)
|
||||
@ -122,7 +104,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn insert_delete() {
|
||||
let mut t = Text::default();
|
||||
let mut t = Text::new();
|
||||
t.insert(0, 0, "Hello", "A");
|
||||
t.insert(5, 5, "world!", "A");
|
||||
t.insert(5, 5, ", ", "B");
|
||||
@ -139,7 +121,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn backspace() {
|
||||
let mut t = Text::default();
|
||||
let mut t = Text::new();
|
||||
t.insert(0, 0, "Hello", "A");
|
||||
|
||||
t.delete_backward(5, 5, "A");
|
||||
@ -151,7 +133,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn delete() {
|
||||
let mut t = Text::default();
|
||||
let mut t = Text::new();
|
||||
t.insert(0, 0, "Hello", "A");
|
||||
|
||||
t.delete_forward(4, 4, "A");
|
||||
@ -163,7 +145,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn linebreak() {
|
||||
let mut t = Text::default();
|
||||
let mut t = Text::new();
|
||||
t.insert(0, 0, "Hello, world!", "A");
|
||||
t.insert_linebreak(6, 6, "A");
|
||||
|
||||
@ -177,20 +159,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn apply_ops() {
|
||||
let mut t_a = Text::default();
|
||||
let mut t_a = Text::new();
|
||||
let ops_a = t_a.insert(0, 0, "Hello, world!", "A");
|
||||
|
||||
let mut t_b = Text::default();
|
||||
let mut t_b = Text::new();
|
||||
t_b.apply_ops(ops_a);
|
||||
|
||||
assert_eq!(t_b.to_string(), "Hello, world!");
|
||||
|
||||
let ops_a = t_a.insert(7, 7, "distributed ", "A");
|
||||
let ops_a = t_a.insert(7,7, "distributed ", "A");
|
||||
t_b.apply_ops(ops_a);
|
||||
|
||||
let ops_b = t_b.insert(7, 7, "cruel ", "B");
|
||||
let ops_b = t_b.insert(7,7, "cruel ", "B");
|
||||
t_a.apply_ops(ops_b);
|
||||
|
||||
|
||||
assert_eq!(t_a.to_string(), "Hello, cruel distributed world!");
|
||||
assert_eq!(t_b.to_string(), "Hello, cruel distributed world!");
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use axum_extra::routing::SpaRouter;
|
||||
use dist_text::text::Text;
|
||||
use std::env;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{broadcast, RwLock};
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
use dist_text::text::Text;
|
||||
|
||||
mod ws;
|
||||
|
||||
|
@ -9,8 +9,8 @@ use axum::{
|
||||
response::IntoResponse,
|
||||
};
|
||||
|
||||
use dist_text::crdts::list::Op;
|
||||
use futures::{sink::SinkExt, stream::StreamExt};
|
||||
use dist_text::crdts::list::Op;
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
@ -84,5 +84,6 @@ async fn handle_socket(stream: WebSocket, state: Arc<AppState>) {
|
||||
tokio::select! {
|
||||
_ = (&mut send_task) => recv_task.abort(),
|
||||
_ = (&mut recv_task) => send_task.abort(),
|
||||
};
|
||||
}
|
||||
;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user