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