use crate::core::merge::merge_type::{MergePatch, MergeResult, MergeType};
use serde_json::Value;
use std::collections::HashMap;
use std::fmt::Debug;
#[derive(Debug, Clone)]
pub struct SimpletonMergeType {
peer_id: String,
content: String,
version: Vec<String>,
seq: u64,
}
impl SimpletonMergeType {
pub fn new(peer_id: &str) -> Self {
Self {
peer_id: peer_id.to_string(),
content: String::new(),
version: Vec::new(),
seq: 0,
}
}
fn generate_version(&mut self) -> String {
self.seq += 1;
format!("{}@{}", self.seq, self.peer_id)
}
fn simple_diff(&self, old_text: &str, new_text: &str) -> (usize, usize, String) {
let a: Vec<char> = old_text.chars().collect();
let b: Vec<char> = new_text.chars().collect();
let mut p = 0;
let len = std::cmp::min(a.len(), b.len());
while p < len && a[p] == b[p] {
p += 1;
}
let mut s = 0;
let len_remaining = std::cmp::min(a.len() - p, b.len() - p);
while s < len_remaining && a[a.len() - s - 1] == b[b.len() - s - 1] {
s += 1;
}
let range_start = p;
let range_end = a.len() - s;
let content: String = b[p..b.len() - s].iter().collect();
(range_start, range_end, content)
}
}
impl MergeType for SimpletonMergeType {
fn name(&self) -> &str {
"simpleton"
}
fn initialize(&mut self, content: &str) -> MergeResult {
self.content = content.to_string();
let version = self.generate_version();
self.version = vec![version.clone()];
MergeResult::success(Some(version), Vec::new())
}
fn apply_patch(&mut self, patch: MergePatch) -> MergeResult {
let mut offset: isize = 0;
let mut last_version = None;
let range_regex = regex::Regex::new(r"\[(\d+):(\d+)\]").unwrap();
if let Some(caps) = range_regex.captures(&patch.range) {
let start_idx: usize = caps[1].parse().unwrap_or(0);
let end_idx: usize = caps[2].parse().unwrap_or(0);
let content_str = match &patch.content {
Value::String(s) => s.clone(),
v => v.to_string(),
};
let chars: Vec<char> = self.content.chars().collect();
let start = (start_idx as isize + offset).max(0) as usize;
let end = (end_idx as isize + offset).max(0) as usize;
if start <= chars.len() && end <= chars.len() && start <= end {
let mut new_chars = chars[..start].to_vec();
new_chars.extend(content_str.chars());
new_chars.extend(&chars[end..]);
let deleted_count = end - start;
let added_count = content_str.chars().count();
offset += added_count as isize - deleted_count as isize;
self.content = new_chars.into_iter().collect();
if let Some(v) = patch.version.clone() {
last_version = Some(v);
}
} else {
return MergeResult::failure(&format!(
"Invalid range [{} : {}] for content length {}",
start,
end,
chars.len()
));
}
}
if let Some(v) = last_version {
self.version = vec![v.clone()];
}
MergeResult::success(patch.version, Vec::new())
}
fn local_edit(&mut self, mut patch: MergePatch) -> MergeResult {
let version = self.generate_version();
patch.version = Some(version.clone());
self.apply_patch(patch.clone())
}
fn get_content(&self) -> String {
self.content.clone()
}
fn get_version(&self) -> Vec<String> {
self.version.clone()
}
fn get_all_versions(&self) -> HashMap<String, Vec<String>> {
let mut map = HashMap::new();
for v in &self.version {
map.insert(v.clone(), Vec::new());
}
map
}
fn prune(&mut self) -> bool {
false
}
fn clone_box(&self) -> Box<dyn MergeType> {
Box::new(self.clone())
}
}