std_mel/text/
compose.rs

1use melodium_core::*;
2use melodium_macro::{check, mel_function, mel_treatment};
3
4/// Rescale stream of strings.
5///
6/// _Rescaling_ means that strings sent throught stream are rearranged according to the `delimiter`.
7///
8/// Unscaled stream can basically be cut at any position:
9/// ```
10/// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean qua"
11/// "m velit, tristique et arcu in, viverra pulvinar ante. Interdum et m"
12/// "alesuada fames ac ante ipsum primis in faucibus. Cras varius, augue"
13/// " ac fringilla placerat, nibh lorem laoreet enim, sed fermentum libe"
14/// " ro justo ut sapien."
15/// ```
16///
17/// While treatments may expect well-defined strings:
18/// ```
19/// "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
20/// "Aenean quam velit, tristique et arcu in, viverra pulvinar ante."
21/// "Interdum et malesuada fames ac ante ipsum primis in faucibus."
22/// "Cras varius, augue ac fringilla placerat, nibh lorem laoreet enim, sed fermentum libero justo ut sapien."
23/// ```
24#[mel_treatment(
25    default delimiter "\n"
26    input unscaled Stream<string>
27    output scaled Stream<string>
28)]
29pub async fn rescale(delimiter: string) {
30    let mut previous = String::new();
31    'main: while let Ok(input) = unscaled
32        .recv_one()
33        .await
34        .map(|val| GetData::<string>::try_data(val).unwrap())
35    {
36        let splits: Vec<&str> = input.split_inclusive(&delimiter).collect();
37        for split in splits {
38            previous.push_str(split);
39            if previous.ends_with(&delimiter) {
40                check!('main, scaled.send_one(previous.into()).await);
41                previous = String::new();
42            }
43        }
44    }
45}
46
47/// Split strings with delimiter.
48///
49/// `text` is splitted according to `delimiter`, and streamed as `splitted` vector.
50/// - `inclusive`: set if the delimiter must be kept at the end of splitted strings (if present).
51///
52/// ```mermaid
53/// graph LR
54///     T("split()")
55///     B["🟦"] -->|vector| T
56///     
57///     T -->|value| O["[🟦 🟦 🟦]"]
58///
59///     style B fill:#ffff,stroke:#ffff
60///     style O fill:#ffff,stroke:#ffff
61/// ```
62#[mel_treatment(
63    default inclusive true
64    input text Stream<string>
65    output splitted Stream<Vec<string>>
66)]
67pub async fn split(delimiter: string, inclusive: bool) {
68    while let Ok(input) = text
69        .recv_many()
70        .await
71        .map(|values| TryInto::<Vec<string>>::try_into(values).unwrap())
72    {
73        let mut output = VecDeque::with_capacity(input.len());
74
75        if inclusive {
76            input.into_iter().for_each(|text| {
77                output.push_back(Value::Vec(
78                    text.split_inclusive(&delimiter)
79                        .map(|s| s.to_string().into())
80                        .collect(),
81                ))
82            });
83        } else {
84            input.into_iter().for_each(|text| {
85                output.push_back(Value::Vec(
86                    text.split(&delimiter)
87                        .map(|s| s.to_string().into())
88                        .collect(),
89                ))
90            });
91        }
92
93        check!(splitted.send_many(TransmissionValue::Other(output)).await);
94    }
95}
96
97/// Split strings with delimiter.
98///
99/// `text` is splitted as `Vec<string>` according to `delimiter`.
100/// - `inclusive`: set if the delimiter must be kept at the end of splitted strings (if present).
101#[mel_function]
102pub fn split(text: string, delimiter: string, inclusive: bool) -> Vec<string> {
103    if inclusive {
104        text.split_inclusive(&delimiter)
105            .map(|s| s.to_string())
106            .collect()
107    } else {
108        text.split(&delimiter).map(|s| s.to_string()).collect()
109    }
110}
111
112/// Trim stream of strings.
113///
114/// Stream strings with leading and trailing whitespace removed.
115/// _Whitespace_ is defined according to the terms of the Unicode Derived Core Property `White_Space`, which includes newlines.
116#[mel_treatment(
117    input text Stream<string>
118    output trimmed Stream<string>
119)]
120pub async fn trim() {
121    while let Ok(mut text) = text
122        .recv_many()
123        .await
124        .map(|values| TryInto::<Vec<string>>::try_into(values).unwrap())
125    {
126        text.iter_mut().for_each(|t| *t = t.trim().to_string());
127
128        check!(trimmed.send_many(text.into()).await);
129    }
130}
131
132/// Trim string.
133///
134/// Return string with leading and trailing whitespace removed.
135/// _Whitespace_ is defined according to the terms of the Unicode Derived Core Property `White_Space`, which includes newlines.
136#[mel_function]
137pub fn trim(text: string) -> string {
138    text.trim().to_string()
139}