From 2f078bdf32566f60c02cf79c7c741d1b50a8bf24 Mon Sep 17 00:00:00 2001 From: Jeff Baskin Date: Mon, 16 Mar 2026 08:56:47 -0400 Subject: [PATCH] Completed basic functions of universal string. --- src/document/field.rs | 87 ++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/src/document/field.rs b/src/document/field.rs index 5d5b054..dd8d0a9 100644 --- a/src/document/field.rs +++ b/src/document/field.rs @@ -584,39 +584,23 @@ struct UniversalString { } impl UniversalString { - fn split_string(text: String) -> Vec { - let holder = text.as_str(); - let mut output = Vec::new(); - for item in holder.split("\u{2029}") { - output.push(item.to_string()); - } + fn new(lang: Language, text: String) -> Self { + let mut output = Self { + paragraphs: HashMap::new(), + revisions: Vec::new(), + }; + output.update(lang, text); output } - fn new(lang: Language, text: String) -> Self { - let input = Self::split_string(text); - let mut paragraphs = HashMap::new(); - let mut revision = Vec::new(); - for paragraph in input { - let mut id = Uuid::new_v4(); - while paragraphs.contains_key(&id) { - id = Uuid::new_v4(); - } - if paragraph != "" { - revision.push(id.clone()); - paragraphs.insert(id, Paragraph::new(lang.clone(), paragraph.to_string())); - } - } - Self { - paragraphs: paragraphs, - revisions: vec![revision], - } + fn get(&self, lang: &Language) -> Option { + let latest = self.revisions.len() - 1; + self.get_revision(latest, lang) } - fn get(&self, lang: &Language) -> Option { - let latest = self.revisions.iter().last().unwrap(); + fn get_revision(&self, rev_num: usize, lang: &Language) -> Option { let mut output = "".to_string(); - for id in latest.iter() { + for id in self.revisions[rev_num].iter() { let paragraph = self.paragraphs.get(id).unwrap(); let text = paragraph.get(lang).unwrap(); output += text; @@ -630,14 +614,12 @@ impl UniversalString { } fn update(&mut self, lang: Language, text: String) { - let input = Self::split_string(text); let mut version = Vec::new(); - for paragraph in input { + for paragraph in text.as_str().split("\u{2029}") { if paragraph != "" { let mut id = Uuid::nil(); for (key, value) in self.paragraphs.iter() { if ¶graph == value.get(&lang).unwrap() { - println!("--- Got here ---"); id = key.clone(); break; } @@ -736,5 +718,50 @@ mod universal_strings { assert_eq!(ustr.get(&lang).unwrap(), expected); assert_eq!(ustr.revision_count(), 1); assert_eq!(ustr.paragraphs.len(), data.len(), "{:?}", ustr); + assert_eq!(ustr.get_revision(0, &lang).unwrap(), initial); + } + + #[test] + fn can_a_paragraph_be_replaced() { + let (lang, mut data) = TestData::english(); + let initial = TestData::to_input(data.clone()); + let mut ustr = UniversalString::new(lang.clone(), initial.clone()); + let position = random_range(..data.len()); + data[position] = "replaced".to_string(); + let expected = TestData::to_input(data.clone()); + ustr.update(lang.clone(), expected.clone()); + assert_eq!(ustr.get(&lang).unwrap(), expected); + assert_eq!(ustr.revision_count(), 1); + assert_eq!(ustr.paragraphs.len(), (data.len() + 1), "{:?}", ustr); + assert_eq!(ustr.get_revision(0, &lang).unwrap(), initial); + } + + #[test] + fn does_not_store_duplicate_data() { + let lang = Language::from_639_1("en").unwrap(); + let mut data = Vec::new(); + for _ in 0..3 { + data.push("same".to_string()); + } + let initial = TestData::to_input(data.clone()); + let mut ustr = UniversalString::new(lang.clone(), initial.clone()); + assert_eq!(ustr.get(&lang).unwrap(), initial); + assert_eq!(ustr.paragraphs.len(), 1, "{:?}", ustr); + } + + #[test] + fn can_text_be_removed() { + let (lang, mut data) = TestData::english(); + let expected_paragraphs = data.len(); + let initial = TestData::to_input(data.clone()); + let mut ustr = UniversalString::new(lang.clone(), initial.clone()); + let position = random_range(..data.len()); + data.remove(position); + let expected = TestData::to_input(data.clone()); + ustr.update(lang.clone(), expected.clone()); + assert_eq!(ustr.get(&lang).unwrap(), expected); + assert_eq!(ustr.revision_count(), 1); + assert_eq!(ustr.paragraphs.len(), expected_paragraphs, "{:?}", ustr); + assert_eq!(ustr.get_revision(0, &lang).unwrap(), initial); } }