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
use super::ContextInformation;
use super::{Frac, Plan, StepResult};

#[derive(Debug, PartialEq, Clone)]
pub(super) struct Base256Plan<T: ContextInformation> {
    /// Number of values not yet written
    ctx: T,
    written: usize,
    cost: Frac,
}

impl<T: ContextInformation> Base256Plan<T> {
    pub(super) fn with_written(mut ctx: T, written: usize) -> Self {
        let cost = if written == 0 {
            // for length byte
            ctx.write(1);
            1
        } else {
            0
        };
        Self {
            ctx,
            written,
            cost: cost.into(), // initial length byte
        }
    }

    pub(super) fn new(ctx: T) -> Self {
        Self::with_written(ctx, 0)
    }

    pub(super) fn context(&self) -> &T {
        &self.ctx
    }
}

impl<T: ContextInformation> Plan for Base256Plan<T> {
    type Context = T;

    fn mode_switch_cost(&self) -> Option<Frac> {
        if self.written >= 250 {
            Some(self.cost + 1)
        } else {
            Some(self.cost)
        }
    }

    fn cost(&self) -> Frac {
        if !self.ctx.has_more_characters() {
            let left = self.ctx.symbol_size_left(0).unwrap_or(1);
            if left > 0 && self.written > 249 {
                // we can must use 1 extra byte for the length
                return self.cost + 1;
            }
        }
        self.cost
    }

    fn write_unlatch(&self) -> T {
        let mut ctx = self.ctx.clone();
        if self.written >= 250 {
            // extra byte for big length
            ctx.write(1);
        }
        ctx
    }

    fn step(&mut self) -> Option<StepResult> {
        let end = !self.ctx.has_more_characters();
        if !end {
            let _ = self.ctx.eat().unwrap();
            self.written += 1;
            self.cost += 1;
            self.ctx.write(1);
            if self.written == 1556 {
                return None;
            }
        }
        Some(StepResult {
            end,
            unbeatable: false,
        })
    }
}