///|
pub struct ThreadInfo {
message_id : String
in_reply_to : String
references : Array[String]
root_id : String
} derive(Eq, Debug)
///|
pub fn thread_info(message : MailMessage) -> ThreadInfo {
let refs = parse_message_id_list(header_value(message.headers, "References"))
let in_reply_to = first_message_id(
header_value(message.headers, "In-Reply-To"),
)
let root = if refs.length() > 0 {
refs[0]
} else if in_reply_to != "" {
in_reply_to
} else {
message.message_id
}
{
message_id: message.message_id,
in_reply_to,
references: refs,
root_id: root,
}
}
///|
pub fn parse_message_id_list(value : String) -> Array[String] {
let out : Array[String] = []
let chars : Array[Char] = []
for ch in value {
chars.push(ch)
}
let mut i = 0
while i < chars.length() {
if chars[i] == '<' {
let end = find_message_id_end(chars, i + 1)
if end > i {
out.push("<" + chars_range_for_thread(chars, i + 1, end) + ">")
i = end + 1
} else {
i = i + 1
}
} else {
i = i + 1
}
}
out
}
///|
fn first_message_id(value : String) -> String {
let ids = parse_message_id_list(value)
if ids.length() > 0 {
ids[0]
} else {
trim_ascii(value)
}
}
///|
fn find_message_id_end(chars : Array[Char], start : Int) -> Int {
let mut i = start
while i < chars.length() {
if chars[i] == '>' {
return i
}
i = i + 1
}
-1
}
///|
fn chars_range_for_thread(
chars : Array[Char],
start : Int,
end : Int,
) -> String {
let mut out = ""
let mut i = start
while i < end {
out = out + chars[i].to_string()
i = i + 1
}
out
}
///|
pub fn same_thread(a : MailMessage, b : MailMessage) -> Bool {
let ta = thread_info(a)
let tb = thread_info(b)
ta.root_id != "" && ta.root_id == tb.root_id
}
///|
pub fn group_thread_roots(
messages : Array[MailMessage],
) -> Array[(String, Int)] {
let roots : Array[(String, Int)] = []
for message in messages {
let root = thread_info(message).root_id
increment_root(roots, root)
}
roots
}
///|
fn increment_root(roots : Array[(String, Int)], root : String) -> Unit {
let key = if root == "" { "(missing)" } else { root }
let mut i = 0
while i < roots.length() {
if roots[i].0 == key {
roots[i] = (roots[i].0, roots[i].1 + 1)
return
}
i = i + 1
}
roots.push((key, 1))
}