1
// This file is derived from ttf-parser, licenced under Apache-2.0.
2
// https://github.com/RazrFalcon/ttf-parser/blob/439aaaebd50eb8aed66302e3c1b51fae047f85b2/src/tables/cff/argstack.rs
3

            
4
use std::fmt::Debug;
5

            
6
use crate::cff::CFFError;
7

            
8
/// Storage for the CFF operand stack with processing CharStrings.
9
pub struct ArgumentsStack<'a, T>
10
where
11
    T: Debug,
12
{
13
    pub data: &'a mut [T],
14
    pub len: usize,
15
    pub max_len: usize,
16
}
17

            
18
impl<'a, T> ArgumentsStack<'a, T>
19
where
20
    T: Copy + Debug,
21
{
22
    pub fn len(&self) -> usize {
23
        self.len
24
    }
25

            
26
    pub fn is_empty(&self) -> bool {
27
        self.len == 0
28
    }
29

            
30
    pub fn push(&mut self, n: T) -> Result<(), CFFError> {
31
        if self.len == self.max_len {
32
            Err(CFFError::ArgumentsStackLimitReached)
33
        } else {
34
            self.data[self.len] = n;
35
            self.len += 1;
36
            Ok(())
37
        }
38
    }
39

            
40
    pub fn at(&self, index: usize) -> T {
41
        self.data[index]
42
    }
43

            
44
    pub fn pop(&mut self) -> T {
45
        debug_assert!(!self.is_empty());
46
        self.len -= 1;
47
        self.data[self.len]
48
    }
49

            
50
    /// pop n values from the stack
51
    pub fn pop_n(&mut self, n: usize) -> &[T] {
52
        debug_assert!(n <= self.len);
53
        self.len -= n;
54
        &self.data[self.len..]
55
    }
56

            
57
    pub fn pop_all(&mut self) -> &[T] {
58
        let len = self.len;
59
        self.len = 0;
60
        &self.data[..len]
61
    }
62

            
63
    pub fn all(&self) -> &[T] {
64
        &self.data[..self.len]
65
    }
66

            
67
    pub fn offset<E>(
68
        &mut self,
69
        offset: usize,
70
        mut func: impl FnMut(&ArgumentsStack<'_, T>) -> Result<(), E>,
71
    ) -> Result<(), E> {
72
        debug_assert!(offset <= self.len);
73
        let temporary_stack = ArgumentsStack {
74
            data: &mut self.data[offset..],
75
            len: self.len - offset,
76
            max_len: self.max_len - offset,
77
        };
78
        func(&temporary_stack)
79
    }
80

            
81
    pub fn reverse(&mut self) {
82
        if self.is_empty() {
83
            return;
84
        }
85

            
86
        // Reverse only the actual data and not the whole stack.
87
        let (first, _) = self.data.split_at_mut(self.len);
88
        first.reverse();
89
    }
90

            
91
    pub fn clear(&mut self) {
92
        self.len = 0;
93
    }
94

            
95
    pub(crate) fn clone_into(&self, data: &'a mut [T]) -> Self {
96
        data[..self.len].clone_from_slice(&self.data[..self.len]);
97
        ArgumentsStack {
98
            data,
99
            len: self.len,
100
            max_len: self.max_len,
101
        }
102
    }
103
}
104

            
105
impl<T: Debug> Debug for ArgumentsStack<'_, T> {
106
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107
        f.debug_list().entries(&self.data[..self.len]).finish()
108
    }
109
}