diff options
author | Philipp Korber <p.korber@1aim.com> | 2018-11-16 15:46:43 +0100 |
---|---|---|
committer | Philipp Korber <p.korber@1aim.com> | 2018-11-16 15:46:43 +0100 |
commit | 652d6f0ffeee7302a2cb51059bef75d8b0bb50be (patch) | |
tree | c3851592642938172f280f7428d43e08b0fe2cbe /headers/src/header_components/utils/text_partition.rs | |
parent | 0947fe8996149fe20a6d47a793f9555790eb2eae (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.rs | 62 |
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 |