1use core::slice;
22
23use crate::message;
24use crate::message::Allocator;
25use crate::message::ReaderSegments;
26use crate::private::read_limiter::ReadLimiter;
27use crate::private::units::*;
28use crate::OutputSegments;
29use crate::{Error, ErrorKind, Result};
30
31pub type SegmentId = u32;
32
33pub unsafe trait ReaderArena {
34 fn get_segment(&self, id: u32) -> Result<(*const u8, u32)>;
36
37 unsafe fn check_offset(
38 &self,
39 segment_id: u32,
40 start: *const u8,
41 offset_in_words: i32,
42 ) -> Result<*const u8> {
43 let (segment_start, segment_len) = self.get_segment(segment_id)?;
44 let this_start: usize = segment_start as usize;
45 let this_size: usize = segment_len as usize * BYTES_PER_WORD;
46 let offset: i64 = i64::from(offset_in_words) * BYTES_PER_WORD as i64;
47 let start_idx = start as usize;
48 if start_idx < this_start || ((start_idx - this_start) as i64 + offset) as usize > this_size
49 {
50 Err(Error::from_kind(
51 ErrorKind::MessageContainsOutOfBoundsPointer,
52 ))
53 } else {
54 unsafe { Ok(start.offset(offset as isize)) }
55 }
56 }
57
58 fn contains_interval(&self, segment_id: u32, start: *const u8, size: usize) -> Result<()>;
59 fn amplified_read(&self, virtual_amount: u64) -> Result<()>;
60
61 fn nesting_limit(&self) -> i32;
62
63 fn size_in_words(&self) -> usize;
64
65 }
69
70pub struct ReaderArenaImpl<S> {
71 segments: S,
72 read_limiter: ReadLimiter,
73 nesting_limit: i32,
74}
75
76#[cfg(feature = "sync_reader")]
77fn _assert_sync() {
78 fn _assert_sync<T: Sync>() {}
79 fn _assert_reader<S: ReaderSegments + Sync>() {
80 _assert_sync::<ReaderArenaImpl<S>>();
81 }
82}
83
84impl<S> ReaderArenaImpl<S>
85where
86 S: ReaderSegments,
87{
88 pub fn new(segments: S, options: message::ReaderOptions) -> Self {
89 let limiter = ReadLimiter::new(options.traversal_limit_in_words);
90 Self {
91 segments,
92 read_limiter: limiter,
93 nesting_limit: options.nesting_limit,
94 }
95 }
96
97 pub fn into_segments(self) -> S {
98 self.segments
99 }
100
101 pub(crate) fn get_segments(&self) -> &S {
102 &self.segments
103 }
104}
105
106unsafe impl<S> ReaderArena for ReaderArenaImpl<S>
107where
108 S: ReaderSegments,
109{
110 fn get_segment(&self, id: u32) -> Result<(*const u8, u32)> {
111 match self.segments.get_segment(id) {
112 Some(seg) => {
113 #[cfg(not(feature = "unaligned"))]
114 {
115 if seg.as_ptr() as usize % BYTES_PER_WORD != 0 {
116 return Err(Error::from_kind(ErrorKind::UnalignedSegment));
117 }
118 }
119
120 Ok((seg.as_ptr(), (seg.len() / BYTES_PER_WORD) as u32))
121 }
122 None => Err(Error::from_kind(ErrorKind::InvalidSegmentId(id))),
123 }
124 }
125
126 fn contains_interval(&self, id: u32, start: *const u8, size_in_words: usize) -> Result<()> {
127 let (segment_start, segment_len) = self.get_segment(id)?;
128 let this_start: usize = segment_start as usize;
129 let this_size: usize = segment_len as usize * BYTES_PER_WORD;
130 let start = start as usize;
131 let size = size_in_words * BYTES_PER_WORD;
132
133 if !(start >= this_start && start - this_start + size <= this_size) {
134 Err(Error::from_kind(
135 ErrorKind::MessageContainsOutOfBoundsPointer,
136 ))
137 } else {
138 self.read_limiter.can_read(size_in_words)
139 }
140 }
141
142 fn amplified_read(&self, virtual_amount: u64) -> Result<()> {
143 self.read_limiter.can_read(virtual_amount as usize)
144 }
145
146 fn nesting_limit(&self) -> i32 {
147 self.nesting_limit
148 }
149
150 fn size_in_words(&self) -> usize {
151 let mut result = 0;
152 for ii in 0..self.segments.len() {
153 if let Some(seg) = self.segments.get_segment(ii as u32) {
154 result += seg.len() / BYTES_PER_WORD;
155 }
156 }
157 result
158 }
159}
160
161pub unsafe trait BuilderArena: ReaderArena {
162 fn allocate(&mut self, segment_id: u32, amount: WordCount32) -> Option<u32>;
163 fn allocate_anywhere(&mut self, amount: u32) -> (SegmentId, u32);
164 fn get_segment_mut(&mut self, id: u32) -> (*mut u8, u32);
165
166 fn as_reader(&self) -> &dyn ReaderArena;
167}
168
169struct BuilderSegment {
171 ptr: *mut u8,
173
174 capacity: u32,
177
178 allocated: u32,
180}
181
182#[cfg(feature = "alloc")]
183type BuilderSegmentArray = alloc::vec::Vec<BuilderSegment>;
184
185#[cfg(not(feature = "alloc"))]
186#[derive(Default)]
187struct BuilderSegmentArray {
188 segment: Option<BuilderSegment>,
190}
191
192#[cfg(not(feature = "alloc"))]
193impl BuilderSegmentArray {
194 fn len(&self) -> usize {
195 match self.segment {
196 Some(_) => 1,
197 None => 0,
198 }
199 }
200
201 fn push(&mut self, segment: BuilderSegment) {
202 if self.segment.is_some() {
203 panic!("multiple segments are not supported in no-alloc mode")
204 }
205 self.segment = Some(segment);
206 }
207}
208
209#[cfg(not(feature = "alloc"))]
210impl core::ops::Index<usize> for BuilderSegmentArray {
211 type Output = BuilderSegment;
212
213 fn index(&self, index: usize) -> &Self::Output {
214 assert_eq!(index, 0);
215 match &self.segment {
216 Some(s) => s,
217 None => panic!("no segment"),
218 }
219 }
220}
221
222#[cfg(not(feature = "alloc"))]
223impl core::ops::IndexMut<usize> for BuilderSegmentArray {
224 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
225 assert_eq!(index, 0);
226 match &mut self.segment {
227 Some(s) => s,
228 None => panic!("no segment"),
229 }
230 }
231}
232
233pub struct BuilderArenaImplInner<A>
234where
235 A: Allocator,
236{
237 allocator: Option<A>, segments: BuilderSegmentArray,
239}
240
241pub struct BuilderArenaImpl<A>
242where
243 A: Allocator,
244{
245 inner: BuilderArenaImplInner<A>,
246}
247
248unsafe impl<A> Send for BuilderArenaImpl<A> where A: Send + Allocator {}
251unsafe impl<A> Sync for BuilderArenaImpl<A> where A: Sync + Allocator {}
252
253impl<A> BuilderArenaImpl<A>
254where
255 A: Allocator,
256{
257 pub fn new(allocator: A) -> Self {
258 Self {
259 inner: BuilderArenaImplInner {
260 allocator: Some(allocator),
261 segments: Default::default(),
262 },
263 }
264 }
265
266 pub fn allocate_segment(&mut self, minimum_size: u32) -> Result<()> {
268 self.inner.allocate_segment(minimum_size)
269 }
270
271 pub fn get_segments_for_output(&self) -> OutputSegments<'_> {
272 let reff = &self.inner;
273 if reff.segments.len() == 1 {
274 let seg = &reff.segments[0];
275
276 let slice = unsafe {
280 slice::from_raw_parts(seg.ptr as *const _, seg.allocated as usize * BYTES_PER_WORD)
281 };
282 OutputSegments::SingleSegment([slice])
283 } else {
284 #[cfg(feature = "alloc")]
285 {
286 let mut v = alloc::vec::Vec::with_capacity(reff.segments.len());
287 for seg in &reff.segments {
288 let slice = unsafe {
290 slice::from_raw_parts(
291 seg.ptr as *const _,
292 seg.allocated as usize * BYTES_PER_WORD,
293 )
294 };
295 v.push(slice);
296 }
297 OutputSegments::MultiSegment(v)
298 }
299 #[cfg(not(feature = "alloc"))]
300 {
301 panic!("invalid number of segments: {}", reff.segments.len());
302 }
303 }
304 }
305
306 pub fn len(&self) -> usize {
307 self.inner.segments.len()
308 }
309
310 pub fn is_empty(&self) -> bool {
311 self.len() == 0
312 }
313
314 pub fn into_allocator(mut self) -> A {
317 self.inner.deallocate_all();
318 self.inner.allocator.take().unwrap()
319 }
320}
321
322unsafe impl<A> ReaderArena for BuilderArenaImpl<A>
323where
324 A: Allocator,
325{
326 fn get_segment(&self, id: u32) -> Result<(*const u8, u32)> {
327 let seg = &self.inner.segments[id as usize];
328 Ok((seg.ptr, seg.allocated))
329 }
330
331 unsafe fn check_offset(
332 &self,
333 _segment_id: u32,
334 start: *const u8,
335 offset_in_words: i32,
336 ) -> Result<*const u8> {
337 unsafe { Ok(start.offset((i64::from(offset_in_words) * BYTES_PER_WORD as i64) as isize)) }
338 }
339
340 fn contains_interval(&self, _id: u32, _start: *const u8, _size: usize) -> Result<()> {
341 Ok(())
342 }
343
344 fn amplified_read(&self, _virtual_amount: u64) -> Result<()> {
345 Ok(())
346 }
347
348 fn nesting_limit(&self) -> i32 {
349 0x7fffffff
350 }
351
352 fn size_in_words(&self) -> usize {
353 let mut result = 0;
354 for ii in 0..self.inner.segments.len() {
355 result += self.inner.segments[ii].allocated as usize
356 }
357 result
358 }
359}
360
361impl<A> BuilderArenaImplInner<A>
362where
363 A: Allocator,
364{
365 fn allocate_segment(&mut self, minimum_size: WordCount32) -> Result<()> {
367 let seg = match &mut self.allocator {
368 Some(a) => a.allocate_segment(minimum_size),
369 None => unreachable!(),
370 };
371 self.segments.push(BuilderSegment {
372 ptr: seg.0,
373 capacity: seg.1,
374 allocated: 0,
375 });
376 Ok(())
377 }
378
379 fn allocate(&mut self, segment_id: u32, amount: WordCount32) -> Option<u32> {
380 let seg = &mut self.segments[segment_id as usize];
381 if amount > seg.capacity - seg.allocated {
382 None
383 } else {
384 let result = seg.allocated;
385 seg.allocated += amount;
386 Some(result)
387 }
388 }
389
390 fn allocate_anywhere(&mut self, amount: u32) -> (SegmentId, u32) {
391 let allocated_len = self.segments.len() as u32;
393 for segment_id in 0..allocated_len {
394 if let Some(idx) = self.allocate(segment_id, amount) {
395 return (segment_id, idx);
396 }
397 }
398
399 self.allocate_segment(amount).expect("allocate new segment");
402 (
403 allocated_len,
404 self.allocate(allocated_len, amount)
405 .expect("use freshly-allocated segment"),
406 )
407 }
408
409 fn deallocate_all(&mut self) {
410 if let Some(a) = &mut self.allocator {
411 #[cfg(feature = "alloc")]
412 for seg in &self.segments {
413 unsafe {
414 a.deallocate_segment(seg.ptr, seg.capacity, seg.allocated);
415 }
416 }
417
418 #[cfg(not(feature = "alloc"))]
419 if let Some(seg) = &self.segments.segment {
420 unsafe {
421 a.deallocate_segment(seg.ptr, seg.capacity, seg.allocated);
422 }
423 }
424 }
425 }
426
427 fn get_segment_mut(&mut self, id: u32) -> (*mut u8, u32) {
428 let seg = &self.segments[id as usize];
429 (seg.ptr, seg.capacity)
430 }
431}
432
433unsafe impl<A> BuilderArena for BuilderArenaImpl<A>
434where
435 A: Allocator,
436{
437 fn allocate(&mut self, segment_id: u32, amount: WordCount32) -> Option<u32> {
438 self.inner.allocate(segment_id, amount)
439 }
440
441 fn allocate_anywhere(&mut self, amount: u32) -> (SegmentId, u32) {
442 self.inner.allocate_anywhere(amount)
443 }
444
445 fn get_segment_mut(&mut self, id: u32) -> (*mut u8, u32) {
446 self.inner.get_segment_mut(id)
447 }
448
449 fn as_reader(&self) -> &dyn ReaderArena {
450 self
451 }
452}
453
454impl<A> Drop for BuilderArenaImplInner<A>
455where
456 A: Allocator,
457{
458 fn drop(&mut self) {
459 self.deallocate_all()
460 }
461}
462
463pub struct NullArena;
464
465unsafe impl ReaderArena for NullArena {
466 fn get_segment(&self, _id: u32) -> Result<(*const u8, u32)> {
467 Err(Error::from_kind(ErrorKind::TriedToReadFromNullArena))
468 }
469
470 unsafe fn check_offset(
471 &self,
472 _segment_id: u32,
473 start: *const u8,
474 offset_in_words: i32,
475 ) -> Result<*const u8> {
476 let offset_in_bytes = (offset_in_words as i64) * BYTES_PER_WORD as i64;
477 unsafe { Ok(start.offset(offset_in_bytes as isize)) }
478 }
479
480 fn contains_interval(&self, _id: u32, _start: *const u8, _size: usize) -> Result<()> {
481 Ok(())
482 }
483
484 fn amplified_read(&self, _virtual_amount: u64) -> Result<()> {
485 Ok(())
486 }
487
488 fn nesting_limit(&self) -> i32 {
489 0x7fffffff
490 }
491
492 fn size_in_words(&self) -> usize {
493 0
494 }
495}
496
497pub struct GeneratedCodeArena {
502 words: &'static [crate::Word],
503}
504
505impl GeneratedCodeArena {
506 pub const fn new(words: &'static [crate::Word]) -> Self {
507 assert!((words.len() as u64) < u32::MAX as u64);
508 Self { words }
509 }
510}
511
512unsafe impl ReaderArena for GeneratedCodeArena {
513 fn get_segment(&self, id: u32) -> Result<(*const u8, u32)> {
514 if id == 0 {
515 Ok((self.words.as_ptr() as *const _, self.words.len() as u32))
516 } else {
517 Err(Error::from_kind(ErrorKind::InvalidSegmentId(id)))
518 }
519 }
520
521 fn contains_interval(&self, id: u32, start: *const u8, size_in_words: usize) -> Result<()> {
522 let (segment_start, segment_len) = self.get_segment(id)?;
523 let this_start: usize = segment_start as usize;
524 let this_size: usize = segment_len as usize * BYTES_PER_WORD;
525 let start = start as usize;
526 let size = size_in_words * BYTES_PER_WORD;
527
528 if !(start >= this_start && start - this_start + size <= this_size) {
529 Err(Error::from_kind(
530 ErrorKind::MessageContainsOutOfBoundsPointer,
531 ))
532 } else {
533 Ok(())
534 }
535 }
536
537 fn amplified_read(&self, _virtual_amount: u64) -> Result<()> {
538 Ok(())
539 }
540
541 fn nesting_limit(&self) -> i32 {
542 0x7fffffff
543 }
544
545 fn size_in_words(&self) -> usize {
546 self.words.len()
547 }
548}