clbarnes commented on code in PR #5206:
URL: https://github.com/apache/arrow-rs/pull/5206#discussion_r1429896465


##########
object_store/src/util.rs:
##########
@@ -167,6 +172,116 @@ fn merge_ranges(ranges: &[std::ops::Range<usize>], 
coalesce: usize) -> Vec<std::
     ret
 }
 
+// Fully-featured HttpRange etc. implementation here 
https://github.com/clbarnes/arrow-rs/blob/httpsuff/object_store/src/util.rs
+
+/// A single range in a `Range` request.
+///
+/// These can be created from [usize] ranges, like
+///
+/// ```rust
+/// let range1: HttpRange = (50..150).into();
+/// let range2: HttpRange = (50..=150).into();
+/// let range3: HttpRange = (50..).into();
+/// let range4: HttpRange = (..150).into();
+/// ```
+///
+/// At present, this is only used internally.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub(crate) enum HttpRange {
+    /// A range with a given first and last bytes.
+    /// If `last > first`, the response should be empty.
+    Range {
+        /// Offset of the first requested byte (0-based).
+        first: usize,
+        /// Offset of the last requested byte; e.g. the range `0-0` will 
request 1 byte.
+        /// If [None], read to end of resource.
+        last: usize,
+    },
+    /// A range defined only by the first byte requested (requests all 
remaining bytes).
+    Offset {
+        /// Offset of the first byte requested.
+        first: usize,
+    },
+    /// A range defined as the number of bytes at the end of the resource.
+    Suffix {
+        /// Number of bytes requested.
+        nbytes: usize,
+    },
+}
+
+impl HttpRange {
+    /// Create a new range which only has an offset.
+    pub fn new_offset(first: usize) -> Self {
+        Self::Offset { first }
+    }
+
+    /// Create a new range with a start and end point.
+    pub fn new_range(first: usize, last: usize) -> Self {
+        Self::Range { first, last }
+    }
+
+    /// Create a new suffix, requesting the last `nbytes` bytes of the 
resource.
+    pub fn new_suffix(nbytes: usize) -> Self {
+        Self::Suffix { nbytes }
+    }
+
+    /// The index of the first byte requested ([None] for suffix).
+    pub fn first_byte(&self) -> Option<usize> {
+        match self {
+            Self::Range { first, .. } => Some(*first),
+            Self::Offset { first } => Some(*first),
+            Self::Suffix { .. } => None,
+        }
+    }
+
+    /// The index of the last byte requested ([None] for offset or suffix).
+    pub fn last_byte(&self) -> Option<usize> {
+        match self {
+            Self::Range { first: _, last } => Some(*last),
+            Self::Offset { .. } => None,
+            Self::Suffix { .. } => None,
+        }
+    }
+}
+
+impl<T: RangeBounds<usize>> From<T> for HttpRange {
+    fn from(value: T) -> Self {
+        use std::ops::Bound::*;
+        let first = match value.start_bound() {
+            Included(i) => *i,
+            Excluded(i) => i.saturating_add(1),
+            Unbounded => 0,
+        };
+        match value.end_bound() {
+            Included(i) => Self::new_range(first, *i),
+            Excluded(i) => Self::new_range(first, i.saturating_sub(1)),
+            Unbounded => Self::new_offset(first),
+        }
+    }
+}
+
+impl Display for HttpRange {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::Range { first, last } => 
f.write_fmt(format_args!("{first}-{last}")),
+            Self::Offset { first } => f.write_fmt(format_args!("{first}-")),
+            Self::Suffix { nbytes } => f.write_fmt(format_args!("-{nbytes}")),
+        }
+    }
+}
+
+pub(crate) fn concrete_range(range: Option<HttpRange>, size: usize) -> 
Range<usize> {

Review Comment:
   I wanted it to cover the `None` case too because turning an 
`Option<HttpRange>` into a concrete `Range` is something we do quite a lot, 
saves seeing `opt_range.map_or(0..len, |r| r.concrete_range(len))` in several 
places. But it's not too much of an issue.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to