aboutsummaryrefslogtreecommitdiff
path: root/rust/src/implementation/passwordmaker/helperthread/message_parsing.rs
blob: 4cda5727de6a98041bf087aa5a8a957be5cdf09b (plain) (blame)
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
use std::sync::mpsc::{Receiver, RecvError};
use super::super::thread_messages::UiToHelper;

pub(super) fn receive_and_get_newest_or_important_command(receiver : &Receiver<UiToHelper>) -> Result<NewestMostImportantCommand, RecvError> {
    let first_message = receive_and_log_error(receiver)?;
    Ok(get_newest_or_important_command(first_message, receiver.try_iter()))
}

pub(super) struct NewestMostImportantCommand(pub UiToHelper);

trait GetNewerOrMoreImportantCommand {
    type Output;
    fn get_newer_or_more_important_command(old: Self::Output, new: Self) -> Self::Output;
    fn convert_first_command(self) -> Self::Output;
}

impl GetNewerOrMoreImportantCommand for UiToHelper {
    type Output = NewestMostImportantCommand;

    fn convert_first_command(self) -> Self::Output{
        NewestMostImportantCommand(self)
    }
    fn get_newer_or_more_important_command(old: Self::Output, new: Self) -> Self::Output {
        match old.0 {
            UiToHelper::Shutdown => old,
            UiToHelper::GeneratePassword(_) => NewestMostImportantCommand(new),
        }
    }
}


fn get_newest_or_important_command<I, It >(first_message: I, other_messages: It) -> I::Output
    where I: GetNewerOrMoreImportantCommand,
    It: Iterator<Item=I> 
{
    other_messages.fold(first_message.convert_first_command(), I::get_newer_or_more_important_command)
}

fn receive_and_log_error(receiver : &Receiver<UiToHelper>) -> Result<UiToHelper, RecvError> {
    match receiver.recv() {
        Ok(x) => Ok(x),
        e => {
                eprintln!("Connection to UI Thread closed unexpectedly.");
                e
             }
    }
}

#[cfg(test)]
mod message_parsing_tests {
    use super::*;

    #[derive(PartialEq, Debug)]
    enum TestPrioritizedEnum {
        Lowest(usize),
        Highest(usize),
        Medium(usize)
    }
    impl TestPrioritizedEnum{
        fn get_prio(&self) -> usize{
            match self {
                TestPrioritizedEnum::Lowest(_) => 0,
                TestPrioritizedEnum::Highest(_) => 2,
                TestPrioritizedEnum::Medium(_) => 1,
            }
        }
    }

    struct TestPrioritizedEnumPrioResult(TestPrioritizedEnum);
    impl GetNewerOrMoreImportantCommand for TestPrioritizedEnum {
        type Output = TestPrioritizedEnumPrioResult;

        fn get_newer_or_more_important_command(old: Self::Output, new: Self) -> Self::Output {
            if old.0.get_prio() > new.get_prio() { old } else { TestPrioritizedEnumPrioResult(new) }
        }

        fn convert_first_command(self) -> Self::Output {
            TestPrioritizedEnumPrioResult(self)
        }
    }

    #[test]
    fn test_get_newest_or_important_command_test(){
        let input1 = vec![TestPrioritizedEnum::Lowest(0), TestPrioritizedEnum::Lowest(1), TestPrioritizedEnum::Lowest(2)];
        let expected1 = TestPrioritizedEnum::Lowest(2);
        let input2 = vec![TestPrioritizedEnum::Medium(0), TestPrioritizedEnum::Lowest(1), TestPrioritizedEnum::Lowest(2)];
        let expected2 = TestPrioritizedEnum::Medium(0);
        let input3 = vec![TestPrioritizedEnum::Lowest(0), TestPrioritizedEnum::Medium(1), TestPrioritizedEnum::Lowest(2)];
        let expected3 = TestPrioritizedEnum::Medium(1);
        let input4 = vec![TestPrioritizedEnum::Medium(0), TestPrioritizedEnum::Lowest(1), TestPrioritizedEnum::Medium(2)];
        let expected4 = TestPrioritizedEnum::Medium(2);
        let input5 = vec![TestPrioritizedEnum::Lowest(0), TestPrioritizedEnum::Lowest(1), TestPrioritizedEnum::Highest(2), TestPrioritizedEnum::Medium(3)];
        let expected5 = TestPrioritizedEnum::Highest(2);
        let data = vec![(input1, expected1), (input2, expected2), (input3, expected3), (input4, expected4), (input5, expected5)];
        for (input, expected) in data {
            let mut it = input.into_iter();
            let first = it.next().unwrap();
            let result = get_newest_or_important_command(first,it);
            assert_eq!(result.0, expected);
        }
    }
}