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