summaryrefslogtreecommitdiffstats
path: root/headers/src/header_components/utils/text_partition.rs
diff options
context:
space:
mode:
authorPhilipp Korber <p.korber@1aim.com>2018-11-16 15:46:43 +0100
committerPhilipp Korber <p.korber@1aim.com>2018-11-16 15:46:43 +0100
commit652d6f0ffeee7302a2cb51059bef75d8b0bb50be (patch)
treec3851592642938172f280f7428d43e08b0fe2cbe /headers/src/header_components/utils/text_partition.rs
parent0947fe8996149fe20a6d47a793f9555790eb2eae (diff)
refactor: merged sources of mail-headers,mail-internals,mail-core, mail
Originally it was palaned to do a merge with `--allow-unrelated-history` but this can not be doesn as `mail-core` has a "invalid" history which has a merge conflict **with itself**. So even rewinding the history on a empty repo is not possible. Instead the code was directly coppied over losing history. But the history is still available in the different `history-backup-*` branches. It is just that the past history is decoupled from the current history.
Diffstat (limited to 'headers/src/header_components/utils/text_partition.rs')
-rw-r--r--headers/src/header_components/utils/text_partition.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/headers/src/header_components/utils/text_partition.rs b/headers/src/header_components/utils/text_partition.rs
new file mode 100644
index 0000000..59047b5
--- /dev/null
+++ b/headers/src/header_components/utils/text_partition.rs
@@ -0,0 +1,62 @@
+use internals::grammar::{is_vchar, is_ws};
+use internals::MailType;
+
+
+#[derive(Copy, Clone, Debug, Fail, PartialEq, Eq, Hash)]
+#[fail(display = "text contained control characters")]
+pub struct PartitionError;
+
+#[derive(Copy, Clone)]
+pub enum Partition<'a> {
+ //from -> to the start of the next block
+ SPACE(&'a str),
+ VCHAR(&'a str)
+}
+
+#[derive(Clone, Copy, PartialEq)]
+enum Type { SPACE, VCHAR }
+
+pub fn partition<'a>( text: &'a str ) -> Result<Vec<Partition<'a>>, PartitionError> {
+ use self::Type::*;
+
+ if text.len() == 0 {
+ return Ok( Vec::new() );
+ }
+
+ // unwrap is ok, as we return earlier if len == 0
+ let start_with_vchar = is_vchar( text.chars().next().unwrap(), MailType::Internationalized);
+
+ let mut partitions = Vec::new();
+ let mut current_type = if start_with_vchar { VCHAR } else { SPACE };
+
+ let mut start_of_current = 0;
+ for (idx, ch) in text.char_indices() {
+ if is_vchar(ch, MailType::Internationalized) {
+ if current_type == SPACE {
+ // idx is the start index of the current char, with is the
+ // (exclusive) end index of the previous char which is the
+ // last char of the Partition we want to push
+ partitions.push(Partition::SPACE(&text[start_of_current..idx]));
+ start_of_current = idx;
+ current_type = VCHAR
+ }
+ } else if is_ws(ch) || ch == '\r' || ch == '\n' {
+ if current_type == VCHAR {
+ partitions.push(Partition::VCHAR(&text[start_of_current..idx]));
+ start_of_current = idx;
+ current_type = SPACE
+ }
+ } else {
+ //TODO look into this error case and especially PartitionError's Display impl
+ return Err(PartitionError);
+ }
+ }
+
+
+ partitions.push( match current_type {
+ SPACE => Partition::SPACE(&text[start_of_current..]),
+ VCHAR => Partition::VCHAR(&text[start_of_current..])
+ } );
+
+ Ok( partitions )
+} \ No newline at end of file