import 'dart:math'; import 'package:quiver/core.dart'; /// Represents an individual range, with an optional start index and optional end index. class RangeHeaderItem implements Comparable { /// The index at which this chunk begins. May be `-1`. final int start; /// The index at which this chunk ends. May be `-1`. final int end; const RangeHeaderItem([this.start = -1, this.end = -1]); /// Joins two items together into the largest possible range. RangeHeaderItem consolidate(RangeHeaderItem other) { if (!(other.overlaps(this))) { throw ArgumentError('The two ranges do not overlap.'); } return RangeHeaderItem(min(start, other.start), max(end, other.end)); } @override int get hashCode => hash2(start, end); @override bool operator ==(other) => other is RangeHeaderItem && other.start == start && other.end == end; bool overlaps(RangeHeaderItem other) { if (other.start <= start) { return other.end < start; } else if (other.start > start) { return other.start <= end; } return false; } @override int compareTo(RangeHeaderItem other) { if (other.start > start) { return -1; } else if (other.start == start) { if (other.end == end) { return 0; } else if (other.end < end) { return 1; } else { return -1; } } else if (other.start < start) { return 1; } else { return -1; } } @override String toString() { if (start > -1 && end > -1) { return '$start-$end'; } else if (start > -1) { return '$start-'; } else { return '-$end'; } } /// Creates a representation of this instance suitable for a `Content-Range` header. /// /// This can only be used if the user request only one range. If not, send a /// `multipart/byteranges` response. /// /// Please adhere to the standard!!! /// http://httpwg.org/specs/rfc7233.html String toContentRange([int? totalSize]) { // var maxIndex = totalSize != null ? (totalSize - 1).toString() : '*'; var s = start > -1 ? start : 0; if (end == -1) { if (totalSize == null) { throw UnsupportedError( 'If the end of this range is unknown, `totalSize` must not be null.'); } else { // if (end == totalSize - 1) { return '$s-${totalSize - 1}/$totalSize'; } } return '$s-$end/$totalSize'; } }