|
| 1 | +use std::io::{Cursor, SeekFrom}; |
| 2 | +use std::ops::Range; |
| 3 | +use std::sync::Arc; |
| 4 | + |
| 5 | +use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; |
1 | 6 | use bytes::Bytes;
|
2 | 7 | use futures::future::{BoxFuture, FutureExt, TryFutureExt};
|
3 | 8 | use object_store::ObjectStore;
|
4 |
| -use std::io::SeekFrom; |
5 |
| -use std::ops::Range; |
6 |
| -use std::sync::Arc; |
7 | 9 |
|
8 | 10 | use crate::error::{AiocogeoError, Result};
|
9 | 11 |
|
@@ -111,3 +113,112 @@ impl AsyncFileReader for ObjectReader {
|
111 | 113 | .boxed()
|
112 | 114 | }
|
113 | 115 | }
|
| 116 | + |
| 117 | +#[derive(Debug, Clone, Copy, Default)] |
| 118 | +pub enum Endianness { |
| 119 | + #[default] |
| 120 | + LittleEndian, |
| 121 | + BigEndian, |
| 122 | +} |
| 123 | + |
| 124 | +/// A wrapper around an [ObjectStore] that provides a seek-oriented interface |
| 125 | +// TODO: in the future add buffering to this |
| 126 | +pub(crate) struct AsyncCursor { |
| 127 | + reader: Box<dyn AsyncFileReader>, |
| 128 | + offset: usize, |
| 129 | + endianness: Endianness, |
| 130 | +} |
| 131 | + |
| 132 | +/// Macro to generate functions to read scalar values from the cursor |
| 133 | +macro_rules! impl_read_byteorder { |
| 134 | + ($method_name:ident, $typ:ty) => { |
| 135 | + pub(crate) async fn $method_name(&mut self) -> $typ { |
| 136 | + let mut buf = Cursor::new(self.read(<$typ>::BITS as usize / 8).await); |
| 137 | + match self.endianness { |
| 138 | + Endianness::LittleEndian => buf.$method_name::<LittleEndian>().unwrap(), |
| 139 | + Endianness::BigEndian => buf.$method_name::<BigEndian>().unwrap(), |
| 140 | + } |
| 141 | + } |
| 142 | + }; |
| 143 | +} |
| 144 | + |
| 145 | +impl AsyncCursor { |
| 146 | + pub(crate) fn new(reader: Box<dyn AsyncFileReader>) -> Self { |
| 147 | + Self { |
| 148 | + reader, |
| 149 | + offset: 0, |
| 150 | + endianness: Default::default(), |
| 151 | + } |
| 152 | + } |
| 153 | + |
| 154 | + pub(crate) fn set_endianness(&mut self, endianness: Endianness) { |
| 155 | + self.endianness = endianness; |
| 156 | + } |
| 157 | + |
| 158 | + pub(crate) fn into_inner(self) -> Box<dyn AsyncFileReader> { |
| 159 | + self.reader |
| 160 | + } |
| 161 | + |
| 162 | + pub(crate) async fn read(&mut self, length: usize) -> Bytes { |
| 163 | + let range = self.offset..self.offset + length; |
| 164 | + self.offset += length; |
| 165 | + self.reader.get_bytes(range).await.unwrap() |
| 166 | + } |
| 167 | + |
| 168 | + /// Read a u8 from the cursor |
| 169 | + pub(crate) async fn read_u8(&mut self) -> u8 { |
| 170 | + let buf = self.read(1).await; |
| 171 | + Cursor::new(buf).read_u8().unwrap() |
| 172 | + } |
| 173 | + |
| 174 | + /// Read a i8 from the cursor |
| 175 | + pub(crate) async fn read_i8(&mut self) -> i8 { |
| 176 | + let buf = self.read(1).await; |
| 177 | + Cursor::new(buf).read_i8().unwrap() |
| 178 | + } |
| 179 | + |
| 180 | + impl_read_byteorder!(read_u16, u16); |
| 181 | + impl_read_byteorder!(read_u32, u32); |
| 182 | + impl_read_byteorder!(read_u64, u64); |
| 183 | + impl_read_byteorder!(read_i16, i16); |
| 184 | + impl_read_byteorder!(read_i32, i32); |
| 185 | + impl_read_byteorder!(read_i64, i64); |
| 186 | + |
| 187 | + pub(crate) async fn read_f32(&mut self) -> f32 { |
| 188 | + let mut buf = Cursor::new(self.read(4).await); |
| 189 | + match self.endianness { |
| 190 | + Endianness::LittleEndian => buf.read_f32::<LittleEndian>().unwrap(), |
| 191 | + Endianness::BigEndian => buf.read_f32::<BigEndian>().unwrap(), |
| 192 | + } |
| 193 | + } |
| 194 | + |
| 195 | + pub(crate) async fn read_f64(&mut self) -> f64 { |
| 196 | + let mut buf = Cursor::new(self.read(8).await); |
| 197 | + match self.endianness { |
| 198 | + Endianness::LittleEndian => buf.read_f64::<LittleEndian>().unwrap(), |
| 199 | + Endianness::BigEndian => buf.read_f64::<BigEndian>().unwrap(), |
| 200 | + } |
| 201 | + } |
| 202 | + |
| 203 | + #[allow(dead_code)] |
| 204 | + pub(crate) fn reader(&self) -> &dyn AsyncFileReader { |
| 205 | + &self.reader |
| 206 | + } |
| 207 | + |
| 208 | + pub(crate) async fn get_range(&mut self, range: Range<usize>) -> Result<Bytes> { |
| 209 | + self.reader.get_bytes(range).await |
| 210 | + } |
| 211 | + |
| 212 | + /// Advance cursor position by a set amount |
| 213 | + pub(crate) fn advance(&mut self, amount: usize) { |
| 214 | + self.offset += amount; |
| 215 | + } |
| 216 | + |
| 217 | + pub(crate) fn seek(&mut self, offset: usize) { |
| 218 | + self.offset = offset; |
| 219 | + } |
| 220 | + |
| 221 | + pub(crate) fn position(&self) -> usize { |
| 222 | + self.offset |
| 223 | + } |
| 224 | +} |
0 commit comments