Skip to content

Commit 20c475a

Browse files
committed
error handling
1 parent 0dae71f commit 20c475a

File tree

2 files changed

+54
-45
lines changed

2 files changed

+54
-45
lines changed

crates/core/src/repository.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1605,7 +1605,7 @@ impl<P, S: IndexedFull> Repository<P, S> {
16051605
///
16061606
// TODO: Document errors
16071607
pub fn open_file(&self, node: &Node) -> RusticResult<OpenFile> {
1608-
Ok(OpenFile::from_node(self, node))
1608+
OpenFile::from_node(self, node)
16091609
}
16101610

16111611
/// Reads an opened file at the given position

crates/core/src/vfs.rs

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ impl Vfs {
456456
pub struct OpenFile {
457457
// The list of blobs
458458
content: Vec<DataId>,
459-
offsets: ContentOffset,
459+
startpoints: ContentStartpoints,
460460
}
461461

462462
impl OpenFile {
@@ -468,26 +468,32 @@ impl OpenFile {
468468
/// * `node` - The `Node` to create the `OpenFile` for
469469
///
470470
/// # Errors
471-
///
472-
// TODO: Document errors
471+
/// - If the index for the needed data blobs cannot be read
473472
///
474473
/// # Returns
475474
///
476475
/// The created `OpenFile`
477-
///
478-
/// # Panics
479-
///
480-
/// * Panics if the `Node` has no content
481-
pub fn from_node<P, S: IndexedFull>(repo: &Repository<P, S>, node: &Node) -> Self {
482-
let content: Vec<_> = node.content.as_ref().unwrap().clone();
483-
484-
let offsets = ContentOffset::from_sizes(
485-
content
486-
.iter()
487-
.map(|id| repo.index().get_data(id).unwrap().data_length() as usize),
488-
);
489-
490-
Self { content, offsets }
476+
pub(crate) fn from_node<P, S: IndexedFull>(
477+
repo: &Repository<P, S>,
478+
node: &Node,
479+
) -> RusticResult<Self> {
480+
let content: Vec<_> = node.content.clone().unwrap_or_default();
481+
482+
let startpoints = ContentStartpoints::from_sizes(content.iter().map(|id| {
483+
Ok(repo
484+
.index()
485+
.get_data(id)
486+
.ok_or_else(|| {
487+
RusticError::new(ErrorKind::Vfs, "blob {blob} is not contained in index")
488+
.attach_context("blob", id.to_string())
489+
})?
490+
.data_length() as usize)
491+
}))?;
492+
493+
Ok(Self {
494+
content,
495+
startpoints,
496+
})
491497
}
492498

493499
/// Read the `OpenFile` at the given `offset` from the `repo`.
@@ -500,7 +506,7 @@ impl OpenFile {
500506
///
501507
/// # Errors
502508
///
503-
// TODO: Document errors
509+
/// - if reading the needed blob(s) from the backend fails
504510
///
505511
/// # Returns
506512
///
@@ -513,7 +519,7 @@ impl OpenFile {
513519
offset: usize,
514520
mut length: usize,
515521
) -> RusticResult<Bytes> {
516-
let (mut i, mut offset) = self.offsets.offset(offset);
522+
let (mut i, mut offset) = self.startpoints.compute_start(offset);
517523

518524
let mut result = BytesMut::with_capacity(length);
519525

@@ -527,43 +533,41 @@ impl OpenFile {
527533
}
528534

529535
let to_copy = (data.len() - offset).min(length);
530-
531536
result.extend_from_slice(&data[offset..offset + to_copy]);
532-
533537
offset = 0;
534-
535538
length -= to_copy;
536-
537539
i += 1;
538540
}
539541

540542
Ok(result.into())
541543
}
542544
}
543545

546+
// helper struct holding blob startpoints of the content
544547
#[derive(Debug)]
545-
struct ContentOffset(Vec<usize>);
548+
struct ContentStartpoints(Vec<usize>);
546549

547-
impl ContentOffset {
548-
fn from_sizes(sizes: impl IntoIterator<Item = usize>) -> Self {
550+
impl ContentStartpoints {
551+
fn from_sizes(sizes: impl IntoIterator<Item = RusticResult<usize>>) -> RusticResult<Self> {
549552
let mut start = 0;
550553
let mut offsets: Vec<_> = sizes
551554
.into_iter()
552-
.map(|size| {
555+
.map(|size| -> RusticResult<_> {
553556
let starts_at = start;
554-
start += size;
555-
starts_at
557+
start += size?;
558+
Ok(starts_at)
556559
})
557-
.collect();
560+
.collect::<RusticResult<_>>()?;
558561

559562
if !offsets.is_empty() {
560563
// offsets is assumed to be partitioned, so we add a starts_at:MAX entry
561564
offsets.push(usize::MAX);
562565
}
563-
Self(offsets)
566+
Ok(Self(offsets))
564567
}
565568

566-
fn offset(&self, mut offset: usize) -> (usize, usize) {
569+
// compute the correct blobid and effective offset from a file offset
570+
fn compute_start(&self, mut offset: usize) -> (usize, usize) {
567571
if self.0.is_empty() {
568572
return (0, 0);
569573
}
@@ -580,26 +584,31 @@ impl ContentOffset {
580584
mod tests {
581585
use super::*;
582586

587+
// helper func
588+
fn startpoints_from_ok_sizes(sizes: impl IntoIterator<Item = usize>) -> ContentStartpoints {
589+
ContentStartpoints::from_sizes(sizes.into_iter().map(Ok)).unwrap()
590+
}
591+
583592
#[test]
584593
fn content_offsets_empty_sizes() {
585-
let offsets = ContentOffset::from_sizes([]);
586-
assert_eq!(offsets.offset(0), (0, 0));
587-
assert_eq!(offsets.offset(42), (0, 0));
594+
let offsets = startpoints_from_ok_sizes([]);
595+
assert_eq!(offsets.compute_start(0), (0, 0));
596+
assert_eq!(offsets.compute_start(42), (0, 0));
588597
}
589598

590599
#[test]
591600
fn content_offsets_size() {
592-
let offsets = ContentOffset::from_sizes([15]);
593-
assert_eq!(offsets.offset(0), (0, 0));
594-
assert_eq!(offsets.offset(5), (0, 5));
595-
assert_eq!(offsets.offset(20), (0, 20));
601+
let offsets = startpoints_from_ok_sizes([15]);
602+
assert_eq!(offsets.compute_start(0), (0, 0));
603+
assert_eq!(offsets.compute_start(5), (0, 5));
604+
assert_eq!(offsets.compute_start(20), (0, 20));
596605
}
597606
#[test]
598607
fn content_offsets_sizes() {
599-
let offsets = ContentOffset::from_sizes([15, 24]);
600-
assert_eq!(offsets.offset(0), (0, 0));
601-
assert_eq!(offsets.offset(5), (0, 5));
602-
assert_eq!(offsets.offset(20), (1, 5));
603-
assert_eq!(offsets.offset(42), (1, 27));
608+
let offsets = startpoints_from_ok_sizes([15, 24]);
609+
assert_eq!(offsets.compute_start(0), (0, 0));
610+
assert_eq!(offsets.compute_start(5), (0, 5));
611+
assert_eq!(offsets.compute_start(20), (1, 5));
612+
assert_eq!(offsets.compute_start(42), (1, 27));
604613
}
605614
}

0 commit comments

Comments
 (0)