1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
910//! A re-useable vector of `Datum` with varying lifetimes.
11//!
12//! This type is meant to allow us to recycle an underlying allocation with
13//! a specific lifetime, under the condition that the vector is emptied before
14//! this happens (to prevent leaking of invalid references).
15//!
16//! It uses `ore::vec::repurpose_allocation` to accomplish this, which contains
17//! unsafe code.
1819use crate::{Datum, RowRef};
2021/// A re-useable vector of `Datum` with no particular lifetime.
22#[derive(Debug, Default, Clone)]
23pub struct DatumVec {
24 outer: Vec<Datum<'static>>,
25}
2627impl DatumVec {
28/// Allocate a new instance.
29pub fn new() -> Self {
30Self { outer: Vec::new() }
31 }
32/// Borrow an instance with a specific lifetime.
33 ///
34 /// When the result is dropped, its allocation will be returned to `self`.
35pub fn borrow<'a>(&'a mut self) -> DatumVecBorrow<'a> {
36let inner = std::mem::take(&mut self.outer);
37 DatumVecBorrow {
38 outer: &mut self.outer,
39 inner,
40 }
41 }
4243/// Borrow an instance with a specific lifetime, and pre-populate with a `Row`.
44pub fn borrow_with<'a>(&'a mut self, row: &'a RowRef) -> DatumVecBorrow<'a> {
45let mut borrow = self.borrow();
46 borrow.extend(row.iter());
47 borrow
48 }
4950/// Borrow an instance with a specific lifetime, and pre-populate with a `Row` with up to
51 /// `limit` elements. If `limit` is greater than the number of elements in `row`, the borrow
52 /// will contain all elements of `row`.
53pub fn borrow_with_limit<'a>(
54&'a mut self,
55 row: &'a RowRef,
56 limit: usize,
57 ) -> DatumVecBorrow<'a> {
58let mut borrow = self.borrow();
59 borrow.extend(row.iter().take(limit));
60 borrow
61 }
62}
6364/// A borrowed allocation of `Datum` with a specific lifetime.
65///
66/// When an instance is dropped, its allocation is returned to the vector from
67/// which it was extracted.
68#[derive(Debug)]
69pub struct DatumVecBorrow<'outer> {
70 outer: &'outer mut Vec<Datum<'static>>,
71 inner: Vec<Datum<'outer>>,
72}
7374impl<'outer> Drop for DatumVecBorrow<'outer> {
75fn drop(&mut self) {
76*self.outer = mz_ore::vec::repurpose_allocation(std::mem::take(&mut self.inner));
77 }
78}
7980impl<'outer> std::ops::Deref for DatumVecBorrow<'outer> {
81type Target = Vec<Datum<'outer>>;
82fn deref(&self) -> &Self::Target {
83&self.inner
84 }
85}
8687impl<'outer> std::ops::DerefMut for DatumVecBorrow<'outer> {
88fn deref_mut(&mut self) -> &mut Self::Target {
89&mut self.inner
90 }
91}
9293#[cfg(test)]
94mod test {
95use super::*;
96use crate::Row;
9798#[mz_ore::test]
99fn miri_test_datum_vec() {
100let mut d = DatumVec::new();
101102assert_eq!(d.borrow().len(), 0);
103104let r = Row::pack_slice(&[Datum::String("first"), Datum::Dummy]);
105106 {
107let borrow = d.borrow_with(&r);
108assert_eq!(borrow.len(), 2);
109assert_eq!(borrow[0], Datum::String("first"));
110 }
111112 {
113// different lifetime, so that rust is happy with the reference lifetimes
114let r2 = Row::pack_slice(&[Datum::String("second")]);
115let mut borrow = d.borrow();
116 borrow.extend(&r);
117 borrow.extend(&r2);
118assert_eq!(borrow.len(), 3);
119assert_eq!(borrow[2], Datum::String("second"));
120 }
121 }
122}