Will leave partially-allocated chunks if fails prematurely, so always check `Self::has_space_for_row` before calling. This method is provided for testing the page store directly; higher-level codepaths are expected to use [`crate::bflatn::ser::write_av_to_page`], which performs similar operations to this method, but handles rollback on failure appropriately. This function will never fail if `Sel
(
&mut self,
fixed_row: &Bytes,
var_len_objects: &[impl AsRef<[u8]>],
var_len_visitor: &impl VarLenMembers,
blob_store: &mut dyn BlobStore,
)
| 1405 | /// and all past, present, and future fixed-length rows stored in this `Page` |
| 1406 | /// must also be of that length. |
| 1407 | pub unsafe fn insert_row( |
| 1408 | &mut self, |
| 1409 | fixed_row: &Bytes, |
| 1410 | var_len_objects: &[impl AsRef<[u8]>], |
| 1411 | var_len_visitor: &impl VarLenMembers, |
| 1412 | blob_store: &mut dyn BlobStore, |
| 1413 | ) -> Result<PageOffset, Error> { |
| 1414 | // Allocate the fixed-len row. |
| 1415 | let fixed_row_size = Size(fixed_row.len() as u16); |
| 1416 | |
| 1417 | // SAFETY: Caller promised that `fixed_row.len()` uses the right `fixed_row_size` |
| 1418 | // and we trust that others have too. |
| 1419 | let fixed_len_offset = unsafe { self.alloc_fixed_len(fixed_row_size)? }; |
| 1420 | |
| 1421 | // Store the fixed-len row. |
| 1422 | let (mut fixed, mut var) = self.split_fixed_var_mut(); |
| 1423 | let row = fixed.get_row_mut(fixed_len_offset, fixed_row_size); |
| 1424 | row.copy_from_slice(fixed_row); |
| 1425 | |
| 1426 | // Store all var-len refs into their appropriate slots in the fixed-len row. |
| 1427 | // SAFETY: |
| 1428 | // - The `fixed_len_offset` given by `alloc_fixed_len` results in `row` |
| 1429 | // being properly aligned for the row type. |
| 1430 | // - Caller promised that `fixed_row.len()` matches the row type size exactly. |
| 1431 | // - `var_len_visitor` is suitable for `fixed_row`. |
| 1432 | let vlr_slot_iter = unsafe { var_len_visitor.visit_var_len_mut(row) }; |
| 1433 | for (var_len_ref_slot, var_len_obj) in vlr_slot_iter.zip(var_len_objects) { |
| 1434 | let (var_len_ref, in_blob) = var.alloc_for_slice(var_len_obj.as_ref())?; |
| 1435 | if in_blob { |
| 1436 | // The blob store insertion will never fail. |
| 1437 | // SAFETY: `alloc_for_slice` always returns a pointer |
| 1438 | // to a `VarLenGranule` in bounds of this page. |
| 1439 | // As `in_blob` holds, it is also unused, as required. |
| 1440 | // We'll now make that granule valid. |
| 1441 | unsafe { |
| 1442 | var.write_large_blob_hash_to_granule(blob_store, var_len_obj, var_len_ref); |
| 1443 | } |
| 1444 | } |
| 1445 | *var_len_ref_slot = var_len_ref; |
| 1446 | } |
| 1447 | |
| 1448 | Ok(fixed_len_offset) |
| 1449 | } |
| 1450 | |
| 1451 | /// Allocates space for a fixed size row of `fixed_row_size` bytes. |
| 1452 | /// |
no test coverage detected