use std::sync::Arc;
use oxigdal_core::error::{IoError, OxiGdalError, Result};
use oxigdal_core::io::{ByteRange, DataSource};
#[derive(Debug, Clone)]
pub struct MemorySource {
data: Arc<Vec<u8>>,
}
impl MemorySource {
#[must_use]
pub fn new(data: Vec<u8>) -> Self {
Self {
data: Arc::new(data),
}
}
#[must_use]
pub fn len(&self) -> usize {
self.data.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
impl DataSource for MemorySource {
fn size(&self) -> Result<u64> {
Ok(self.data.len() as u64)
}
fn read_range(&self, range: ByteRange) -> Result<Vec<u8>> {
if range.end as usize > self.data.len() || range.start > range.end {
return Err(OxiGdalError::Io(IoError::UnexpectedEof {
offset: range.start,
}));
}
Ok(self.data[range.start as usize..range.end as usize].to_vec())
}
fn supports_range_requests(&self) -> bool {
true
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn size_reports_buffer_length() {
let src = MemorySource::new(vec![0u8; 42]);
assert_eq!(src.size().expect("size"), 42);
assert_eq!(src.len(), 42);
assert!(!src.is_empty());
}
#[test]
fn read_range_returns_slice() {
let src = MemorySource::new(vec![10, 20, 30, 40, 50]);
let out = src
.read_range(ByteRange::from_offset_length(1, 3))
.expect("read");
assert_eq!(out, vec![20, 30, 40]);
}
#[test]
fn read_past_eof_errors() {
let src = MemorySource::new(vec![1, 2, 3]);
assert!(
src.read_range(ByteRange::from_offset_length(2, 10))
.is_err()
);
}
#[test]
fn clone_shares_buffer() {
let src = MemorySource::new(vec![7u8; 8]);
let clone = src.clone();
assert_eq!(clone.size().expect("size"), 8);
assert!(src.supports_range_requests());
}
}