risingwave_expr_impl/scalar/
translate.rs

1// Copyright 2025 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::HashMap;
16
17use risingwave_expr::function;
18
19#[function("translate(varchar, varchar, varchar) -> varchar")]
20pub fn translate(s: &str, match_str: &str, replace_str: &str, writer: &mut impl std::fmt::Write) {
21    let mut char_map = HashMap::new();
22    let mut match_chars = match_str.chars();
23    let mut replace_chars = replace_str.chars();
24
25    loop {
26        let m = match_chars.next();
27        let r = replace_chars.next();
28        if let Some(match_c) = m {
29            char_map.entry(match_c).or_insert(r);
30        } else {
31            break;
32        }
33    }
34
35    let iter = s.chars().filter_map(|c| match char_map.get(&c) {
36        Some(Some(m)) => Some(*m),
37        Some(None) => None,
38        None => Some(c),
39    });
40    for c in iter {
41        writer.write_char(c).unwrap();
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn test_translate() {
51        let cases = [
52            ("hello world", "lo", "12", "he112 w2r1d"),
53            (
54                "人之初,性本善。性相近,习相远。",
55                "人性。",
56                "abcd",
57                "a之初,b本善cb相近,习相远c",
58            ),
59            (
60                "奇点无限 RisingWave Labs",
61                "Labs ",
62                "1234",
63                "奇点无限Ri4ingW2ve1234",
64            ),
65        ];
66
67        for (s, match_str, replace_str, expected) in cases {
68            let mut writer = String::new();
69            translate(s, match_str, replace_str, &mut writer);
70            assert_eq!(writer, expected);
71        }
72    }
73}