buffer.rs 6.44 KB
Newer Older
1
// Copyright 2018-2021 Parity Technologies (UK) Ltd.
2
3
4
5
6
7
8
9
10
11
12
13
14
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

15
/// A static buffer with 16 kB of capacity.
16
pub struct StaticBuffer {
17
    /// The static buffer with a total capacity of 16 kB.
18
19
20
21
22
    buffer: [u8; Self::CAPACITY],
}

impl StaticBuffer {
    /// The capacity of the static buffer.
23
    const CAPACITY: usize = 1 << 14; // 16 kB
24
25
26
27
28
29
30

    /// Creates a new static buffer.
    pub const fn new() -> Self {
        Self {
            buffer: [0; Self::CAPACITY],
        }
    }
Hero Bird's avatar
Hero Bird committed
31
}
32

Hero Bird's avatar
Hero Bird committed
33
34
35
36
37
impl core::ops::Index<core::ops::RangeFull> for StaticBuffer {
    type Output = [u8];

    fn index(&self, index: core::ops::RangeFull) -> &Self::Output {
        core::ops::Index::index(&self.buffer[..], index)
38
    }
Hero Bird's avatar
Hero Bird committed
39
}
40

Hero Bird's avatar
Hero Bird committed
41
42
43
impl core::ops::IndexMut<core::ops::RangeFull> for StaticBuffer {
    fn index_mut(&mut self, index: core::ops::RangeFull) -> &mut Self::Output {
        core::ops::IndexMut::index_mut(&mut self.buffer[..], index)
44
    }
Hero Bird's avatar
Hero Bird committed
45
}
46

47
48
49
/// Utility to allow for non-heap allocating encoding into a static buffer.
///
/// Required by `ScopedBuffer` internals.
Hero Bird's avatar
Hero Bird committed
50
51
52
53
54
55
56
57
struct EncodeScope<'a> {
    buffer: &'a mut [u8],
    len: usize,
}

impl<'a> From<&'a mut [u8]> for EncodeScope<'a> {
    fn from(buffer: &'a mut [u8]) -> Self {
        Self { buffer, len: 0 }
58
59
60
    }
}

Hero Bird's avatar
Hero Bird committed
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
impl<'a> EncodeScope<'a> {
    /// Returns the capacity of the encoded scope.
    pub fn capacity(&self) -> usize {
        self.buffer.len()
    }

    /// Returns the length of the encoded scope.
    pub fn len(&self) -> usize {
        self.len
    }

    /// Returns the internal mutable byte slice.
    pub fn into_buffer(self) -> &'a mut [u8] {
        self.buffer
    }
}

impl<'a> scale::Output for EncodeScope<'a> {
79
    fn write(&mut self, bytes: &[u8]) {
Hero Bird's avatar
Hero Bird committed
80
81
82
83
84
85
        debug_assert!(
            self.len() + bytes.len() <= self.capacity(),
            "encode scope buffer overflowed. capacity is {} but last write index is {}",
            self.capacity(),
            self.len() + bytes.len(),
        );
86
87
88
89
90
91
92
        let start = self.len;
        let len_bytes = bytes.len();
        self.buffer[start..(start + len_bytes)].copy_from_slice(bytes);
        self.len += len_bytes;
    }

    fn push_byte(&mut self, byte: u8) {
Hero Bird's avatar
Hero Bird committed
93
94
95
96
97
98
        debug_assert_ne!(
            self.len(),
            self.capacity(),
            "encode scope buffer overflowed. capacity is {} and buffer is already full",
            self.capacity(),
        );
99
100
101
102
103
        self.buffer[self.len] = byte;
        self.len += 1;
    }
}

Hero Bird's avatar
Hero Bird committed
104
105
106
107
/// Scoped access to an underlying bytes buffer.
///
/// # Note
///
108
/// This is used to efficiently chunk up ink!'s internal static 16 kB buffer
Hero Bird's avatar
Hero Bird committed
109
110
111
/// into smaller sub buffers for processing different parts of computations.
#[derive(Debug)]
pub struct ScopedBuffer<'a> {
112
    offset: usize,
Hero Bird's avatar
Hero Bird committed
113
114
    buffer: &'a mut [u8],
}
115

Hero Bird's avatar
Hero Bird committed
116
117
impl<'a> From<&'a mut [u8]> for ScopedBuffer<'a> {
    fn from(buffer: &'a mut [u8]) -> Self {
118
        Self { offset: 0, buffer }
119
120
121
    }
}

Hero Bird's avatar
Hero Bird committed
122
impl<'a> ScopedBuffer<'a> {
123
124
    /// Splits the scoped buffer into yet another piece to operate on it temporarily.
    ///
125
    /// The split buffer will have an offset of 0 but be offset by `self`'s offset.
126
127
128
129
130
131
132
    pub fn split(&mut self) -> ScopedBuffer {
        ScopedBuffer {
            offset: 0,
            buffer: &mut self.buffer[self.offset..],
        }
    }

Hero Bird's avatar
Hero Bird committed
133
134
    /// Returns the first `len` bytes of the buffer as mutable slice.
    pub fn take(&mut self, len: usize) -> &'a mut [u8] {
135
136
        debug_assert_eq!(self.offset, 0);
        debug_assert!(len <= self.buffer.len());
Hero Bird's avatar
Hero Bird committed
137
138
139
140
141
142
143
144
145
146
147
148
        let len_before = self.buffer.len();
        let buffer = core::mem::take(&mut self.buffer);
        let (lhs, rhs) = buffer.split_at_mut(len);
        self.buffer = rhs;
        debug_assert_eq!(lhs.len(), len);
        let len_after = self.buffer.len();
        debug_assert_eq!(len_before - len_after, len);
        lhs
    }

    /// Returns a buffer scope filled with `bytes` with the proper length.
    pub fn take_bytes(&mut self, bytes: &[u8]) -> &'a mut [u8] {
149
        debug_assert_eq!(self.offset, 0);
Hero Bird's avatar
Hero Bird committed
150
151
152
153
154
155
156
157
158
159
160
        let buffer = self.take(bytes.len());
        buffer.copy_from_slice(bytes);
        buffer
    }

    /// Encode the given value into the scoped buffer and return the sub slice
    /// containing all the encoded bytes.
    pub fn take_encoded<T>(&mut self, value: &T) -> &'a mut [u8]
    where
        T: scale::Encode,
    {
161
        debug_assert_eq!(self.offset, 0);
Hero Bird's avatar
Hero Bird committed
162
163
164
165
166
167
168
169
        let buffer = core::mem::take(&mut self.buffer);
        let mut encode_scope = EncodeScope::from(buffer);
        scale::Encode::encode_to(&value, &mut encode_scope);
        let encode_len = encode_scope.len();
        let _ = core::mem::replace(&mut self.buffer, encode_scope.into_buffer());
        self.take(encode_len)
    }

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
    /// Appends the encoding of `value` to the scoped buffer.
    ///
    /// Does not return the buffer immediately so that other values can be appended
    /// afterwards. The [`take_appended`] method shall be used to return the buffer
    /// that includes all appended encodings as a single buffer.
    pub fn append_encoded<T>(&mut self, value: &T)
    where
        T: scale::Encode,
    {
        let offset = self.offset;
        let buffer = core::mem::take(&mut self.buffer);
        let mut encode_scope = EncodeScope::from(&mut buffer[offset..]);
        scale::Encode::encode_to(&value, &mut encode_scope);
        let encode_len = encode_scope.len();
        self.offset += encode_len;
        let _ = core::mem::replace(&mut self.buffer, buffer);
    }

    /// Returns the buffer containing all encodings appended via [`append_encoded`]
    /// in a single byte buffer.
    pub fn take_appended(&mut self) -> &'a mut [u8] {
        debug_assert_ne!(self.offset, 0);
        let offset = self.offset;
        self.offset = 0;
        self.take(offset)
    }

Hero Bird's avatar
Hero Bird committed
197
198
    /// Returns all of the remaining bytes of the buffer as mutable slice.
    pub fn take_rest(self) -> &'a mut [u8] {
199
200
        debug_assert_eq!(self.offset, 0);
        debug_assert!(!self.buffer.is_empty());
Hero Bird's avatar
Hero Bird committed
201
        self.buffer
202
203
    }
}