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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! This crate provides a `recycle` extension method for Vec.
//! It's intended to change the type of the Vec while "recycling"
//! the underlying allocation. This is a trick that is useful especially
//! when storing data with short lifetimes in Vec:
//! ```
//! # use std::error::Error;
//! # use crate::recycle_vec::VecExt;
//! #
//! # struct Stream(bool);
//! #
//! # impl Stream {
//! # fn new() -> Self {
//! # Stream(false)
//! # }
//! #
//! # fn next(&mut self) -> Option<&[u8]> {
//! # if self.0 {
//! # None
//! # } else {
//! # self.0 = true;
//! # Some(&b"foo"[..])
//! # }
//! # }
//! # }
//! #
//! # fn process(input: &[Object<'_>]) -> Result<(), Box<dyn Error>> {
//! # for obj in input {
//! # let _ = obj.reference;
//! # }
//! # Ok(())
//! # }
//! #
//! # struct Object<'a> {
//! # reference: &'a [u8],
//! # }
//! #
//! # fn deserialize<'a>(input: &'a [u8], output: &mut Vec<Object<'a>>) -> Result<(), Box<dyn Error>> {
//! # output.push(Object { reference: input });
//! # Ok(())
//! # }
//! #
//! # fn main() -> Result<(), Box<dyn Error>> {
//! # let mut stream = Stream::new();
//! let mut objects: Vec<Object<'static>> = Vec::new(); // Any lifetime goes here
//!
//! while let Some(byte_chunk) = stream.next() { // `byte_chunk` lifetime starts
//! let mut temp: Vec<Object<'_>> = objects.recycle(); // `temp` lifetime starts
//!
//! // Zero-copy parsing; deserialized `Object`s have references to `byte_chunk`
//! deserialize(byte_chunk, &mut temp)?;
//! process(&temp)?;
//!
//! objects = temp.recycle(); // `temp` lifetime ends
//! } // `byte_chunk` lifetime ends
//! # Ok(())
//! # }
//! ```
//! # Notes about safety
//! This crate uses internally `unsafe` to achieve it's functionality.
//! However, it provides a safe interface. To achieve safety, it does
//! the following precautions:
//! 1. It truncates the `Vec` to zero length, dropping all the values.
//! This ensures that no values of arbitrary types are transmuted
//! accidentally.
//! 2. It checks that the sizes and alignments of the source and target
//! types match. This ensures that the underlying block of memory backing
//! `Vec` is compatible layout-wise. The sizes and alignments are checked
//! statically, so if the compile will fail in case of a mismatch.
//! 3. It creates a new `Vec` value using `from_raw_parts`, instead of
//! transmuting, an operation whose soundness would be questionable.
extern crate alloc;
use Vec;
/// A trait that provides an API for recycling Vec's internal buffers
/// Tests that `recycle` successfully re-interprets the type to have different lifetime from the original
/// Tests that `recycle` successfully re-interprets the type itself