use crate::error::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ByteRange {
pub start: u64,
pub end: u64,
}
impl ByteRange {
#[must_use]
pub const fn new(start: u64, end: u64) -> Self {
Self { start, end }
}
#[must_use]
pub const fn from_offset_length(offset: u64, length: u64) -> Self {
Self {
start: offset,
end: offset + length,
}
}
#[must_use]
pub const fn len(&self) -> u64 {
self.end - self.start
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.start >= self.end
}
#[must_use]
pub const fn overlaps(&self, other: &Self) -> bool {
self.start < other.end && self.end > other.start
}
#[must_use]
pub const fn is_adjacent(&self, other: &Self) -> bool {
self.end == other.start || self.start == other.end
}
#[must_use]
pub fn merge(&self, other: &Self) -> Option<Self> {
if self.overlaps(other) || self.is_adjacent(other) {
Some(Self {
start: self.start.min(other.start),
end: self.end.max(other.end),
})
} else {
None
}
}
}
pub trait DataSource: Send + Sync {
fn size(&self) -> Result<u64>;
fn read_range(&self, range: ByteRange) -> Result<Vec<u8>>;
fn read_ranges(&self, ranges: &[ByteRange]) -> Result<Vec<Vec<u8>>> {
ranges.iter().map(|r| self.read_range(*r)).collect()
}
fn supports_range_requests(&self) -> bool {
true
}
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
pub trait AsyncDataSource: Send + Sync {
async fn size(&self) -> Result<u64>;
async fn read_range(&self, range: ByteRange) -> Result<Vec<u8>>;
async fn read_ranges(&self, ranges: &[ByteRange]) -> Result<Vec<Vec<u8>>> {
let mut results = Vec::with_capacity(ranges.len());
for range in ranges {
results.push(self.read_range(*range).await?);
}
Ok(results)
}
fn supports_range_requests(&self) -> bool {
true
}
}
pub trait DataSink: Send + Sync {
fn write_at(&mut self, offset: u64, data: &[u8]) -> Result<()>;
fn append(&mut self, data: &[u8]) -> Result<u64>;
fn flush(&mut self) -> Result<()>;
fn truncate(&mut self, size: u64) -> Result<()>;
fn size(&self) -> Result<u64>;
}
pub trait RasterRead {
type Buffer;
fn read_region(
&self,
band: u32,
x_offset: u64,
y_offset: u64,
width: u64,
height: u64,
) -> Result<Self::Buffer>;
fn read_tile(&self, band: u32, tile_col: u32, tile_row: u32) -> Result<Self::Buffer>;
}
pub trait RasterWrite {
type Buffer;
fn write_region(
&mut self,
band: u32,
x_offset: u64,
y_offset: u64,
data: &Self::Buffer,
) -> Result<()>;
fn write_tile(
&mut self,
band: u32,
tile_col: u32,
tile_row: u32,
data: &Self::Buffer,
) -> Result<()>;
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
pub trait AsyncRasterRead: Send + Sync {
type Buffer: Send;
async fn read_region(
&self,
band: u32,
x_offset: u64,
y_offset: u64,
width: u64,
height: u64,
) -> Result<Self::Buffer>;
async fn read_tile(&self, band: u32, tile_col: u32, tile_row: u32) -> Result<Self::Buffer>;
}
pub trait OverviewSupport {
fn overview_count(&self) -> u32;
fn overview_dimensions(&self, level: u32) -> Option<(u64, u64)>;
}
pub trait CogSupport: OverviewSupport {
fn tile_size(&self) -> (u32, u32);
fn tile_count(&self) -> (u32, u32);
fn tile_byte_range(&self, level: u32, tile_col: u32, tile_row: u32) -> Option<ByteRange>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_byte_range() {
let range = ByteRange::new(100, 200);
assert_eq!(range.len(), 100);
assert!(!range.is_empty());
let empty = ByteRange::new(100, 100);
assert!(empty.is_empty());
}
#[test]
fn test_byte_range_overlap() {
let a = ByteRange::new(0, 100);
let b = ByteRange::new(50, 150);
let c = ByteRange::new(200, 300);
assert!(a.overlaps(&b));
assert!(b.overlaps(&a));
assert!(!a.overlaps(&c));
}
#[test]
fn test_byte_range_merge() {
let a = ByteRange::new(0, 100);
let b = ByteRange::new(100, 200);
let c = ByteRange::new(50, 150);
let merged_adj = a.merge(&b);
assert!(merged_adj.is_some());
let merged = merged_adj.expect("merge should work");
assert_eq!(merged.start, 0);
assert_eq!(merged.end, 200);
let merged_overlap = a.merge(&c);
assert!(merged_overlap.is_some());
let merged2 = merged_overlap.expect("merge should work");
assert_eq!(merged2.start, 0);
assert_eq!(merged2.end, 150);
let d = ByteRange::new(300, 400);
assert!(a.merge(&d).is_none());
}
#[test]
fn test_from_offset_length() {
let range = ByteRange::from_offset_length(100, 50);
assert_eq!(range.start, 100);
assert_eq!(range.end, 150);
assert_eq!(range.len(), 50);
}
}