fix(rust): fix string error in kmp

This commit is contained in:
ZhuJHua
2024-12-01 07:51:33 +08:00
parent 00e7c3a966
commit 163d030cab
7 changed files with 150 additions and 33 deletions

View File

@@ -1,16 +1,16 @@
use flutter_rust_bridge::frb;
use std::collections::HashMap;
pub fn build_prefix_table(pattern: &str) -> Vec<usize> {
pub fn build_prefix_table(pattern: &[char]) -> Vec<usize> {
let m = pattern.len();
let mut prefix_table = vec![0; m];
let mut j = 0;
for i in 1..m {
while j > 0 && pattern.chars().nth(i) != pattern.chars().nth(j) {
while j > 0 && pattern[i] != pattern[j] {
j = prefix_table[j - 1];
}
if pattern.chars().nth(i) == pattern.chars().nth(j) {
if pattern[i] == pattern[j] {
j += 1;
}
prefix_table[i] = j;
@@ -20,16 +20,18 @@ pub fn build_prefix_table(pattern: &str) -> Vec<usize> {
}
pub fn kmp_search(text: &str, pattern: &str) -> Vec<usize> {
let m = pattern.len();
let prefix_table = build_prefix_table(pattern);
let text_chars: Vec<char> = text.chars().collect();
let pattern_chars: Vec<char> = pattern.chars().collect();
let m = pattern_chars.len();
let prefix_table = build_prefix_table(&pattern_chars);
let mut matches = Vec::new();
let mut j = 0;
for (i, c) in text.chars().enumerate() {
while j > 0 && Some(c) != pattern.chars().nth(j) {
for (i, &c) in text_chars.iter().enumerate() {
while j > 0 && c != pattern_chars[j] {
j = prefix_table[j - 1];
}
if Some(c) == pattern.chars().nth(j) {
if c == pattern_chars[j] {
j += 1;
}
if j == m {
@@ -58,7 +60,6 @@ impl Kmp {
if !match_entries.contains_key(&index)
|| match_entries[&index].0.len() < pattern.len()
{
// 确保在相同索引位置,优先使用较长的模式
match_entries.insert(index, (pattern, replacement));
}
}
@@ -66,15 +67,21 @@ impl Kmp {
let mut result = String::new();
let mut last_index = 0;
let mut match_entries: Vec<_> = match_entries.into_iter().collect();
match_entries.sort_by_key(|&(index, _)| index);
let text_chars: Vec<char> = text.chars().collect();
for (index, (pattern, replacement)) in match_entries {
if index >= last_index {
result.push_str(&text[last_index..index]);
let start_byte_index = text_chars[..index]
.iter()
.map(|c| c.len_utf8())
.sum::<usize>();
let end_byte_index = start_byte_index + pattern.len();
if start_byte_index >= last_index {
result.push_str(&text[last_index..start_byte_index]);
result.push_str(replacement);
last_index = index + pattern.len();
last_index = end_byte_index;
}
}

View File

@@ -190,7 +190,7 @@ fn wire__crate__api__kmp__build_prefix_table_impl(
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_pattern = <String>::sse_decode(&mut deserializer);
let api_pattern = <Vec<char>>::sse_decode(&mut deserializer);
deserializer.end();
move |context| {
transform_result_sse::<_, ()>((move || {
@@ -340,6 +340,14 @@ impl SseDecode for Kmp {
}
}
impl SseDecode for char {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut inner = <String>::sse_decode(deserializer);
return inner.chars().next().unwrap();
}
}
impl SseDecode for std::collections::HashMap<String, String> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@@ -404,6 +412,18 @@ impl SseDecode for i32 {
}
}
impl SseDecode for Vec<char> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut len_ = <i32>::sse_decode(deserializer);
let mut ans_ = vec![];
for idx_ in 0..len_ {
ans_.push(<char>::sse_decode(deserializer));
}
return ans_;
}
}
impl SseDecode for Vec<String> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@@ -644,6 +664,13 @@ impl SseEncode for Kmp {
}
}
impl SseEncode for char {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<String>::sse_encode(self.to_string(), serializer);
}
}
impl SseEncode for std::collections::HashMap<String, String> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
@@ -713,6 +740,16 @@ impl SseEncode for i32 {
}
}
impl SseEncode for Vec<char> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<i32>::sse_encode(self.len() as _, serializer);
for item in self {
<char>::sse_encode(item, serializer);
}
}
}
impl SseEncode for Vec<String> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {