Skip to main content

htsget_storage/
types.rs

1use crate::error::{Result, StorageError};
2use htsget_config::types::{Class, Headers, Url};
3use http::HeaderMap;
4use std::borrow::Cow;
5use std::cmp::Ordering;
6use std::fmt;
7use std::fmt::{Display, Formatter};
8use tracing::instrument;
9
10/// A DataBlock is either a range of bytes, or a data blob that gets transformed into a data uri.
11#[derive(Debug, PartialEq, Eq)]
12pub enum DataBlock {
13  Range(BytesPosition),
14  Data(Vec<u8>, Option<Class>),
15}
16
17impl DataBlock {
18  /// Convert a vec of bytes positions to a vec of data blocks. Merges bytes positions.
19  pub fn from_bytes_positions(positions: Vec<BytesPosition>) -> Vec<Self> {
20    BytesPosition::merge_all(positions)
21      .into_iter()
22      .map(DataBlock::Range)
23      .collect()
24  }
25
26  /// Check whether this block is empty.
27  pub fn is_empty(&self) -> bool {
28    match self {
29      DataBlock::Range(range) => range.is_empty(),
30      DataBlock::Data(data, _) => data.is_empty(),
31    }
32  }
33
34  /// Update the classes of all blocks so that they all contain a class, or None. Does not merge
35  /// byte positions.
36  pub fn update_classes(blocks: Vec<Self>) -> Vec<Self> {
37    if blocks.iter().all(|block| match block {
38      DataBlock::Range(range) => range.class.is_some(),
39      DataBlock::Data(_, class) => class.is_some(),
40    }) {
41      blocks
42    } else {
43      blocks
44        .into_iter()
45        .map(|block| match block {
46          DataBlock::Range(range) => DataBlock::Range(range.set_class(None)),
47          DataBlock::Data(data, _) => DataBlock::Data(data, None),
48        })
49        .collect()
50    }
51  }
52}
53
54/// A byte position has an inclusive start value, and an exclusive end value. This is analogous to
55/// query start and end parameters. The class represents the class type for this byte position when
56/// formatted into url responses. The class is set to `Header` for byte positions containing only
57/// header bytes, `Body` for byte positions containing only body bytes, and None for byte positions
58/// with a mix of header and body bytes.
59#[derive(Clone, Debug, Default, PartialEq, Eq)]
60pub struct BytesPosition {
61  start: Option<u64>,
62  end: Option<u64>,
63  class: Option<Class>,
64}
65
66/// A bytes range has an inclusive start and end value. This is analogous to http bytes ranges.
67#[derive(Clone, Debug, Default, PartialEq, Eq)]
68pub struct BytesRange {
69  start: Option<u64>,
70  end: Option<u64>,
71}
72
73impl From<&BytesRange> for String {
74  fn from(ranges: &BytesRange) -> Self {
75    if ranges.start.is_none() && ranges.end.is_none() {
76      return "".to_string();
77    }
78    ranges.to_string()
79  }
80}
81
82impl Display for BytesRange {
83  fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
84    match (self.start, self.end) {
85      (Some(start), Some(end)) => write!(f, "bytes={start}-{end}"),
86      (Some(0), None) | (None, None) => write!(f, ""),
87      (Some(start), None) => write!(f, "bytes={start}-"),
88      (None, Some(end)) => write!(f, "bytes=0-{end}"),
89    }
90  }
91}
92
93impl TryFrom<&BytesPosition> for BytesRange {
94  type Error = StorageError;
95
96  fn try_from(pos: &BytesPosition) -> Result<Self> {
97    if pos.is_empty() {
98      return Err(StorageError::InternalError(format!(
99        "cannot convert a bytes position with no bytes to a bytes range: {pos:?}"
100      )));
101    }
102
103    Ok(Self::new(pos.start, pos.end.map(|value| value - 1)))
104  }
105}
106
107impl BytesRange {
108  pub fn new(start: Option<u64>, end: Option<u64>) -> Self {
109    Self { start, end }
110  }
111}
112
113/// A builder for [BytesPosition].
114#[derive(Clone, Debug, Default)]
115pub struct BytesPositionBuilder {
116  start: Option<u64>,
117  end: Option<u64>,
118  class: Option<Class>,
119}
120
121impl BytesPositionBuilder {
122  pub fn with_start(mut self, start: u64) -> Self {
123    self.start = Some(start);
124    self
125  }
126
127  pub fn set_start(mut self, start: Option<u64>) -> Self {
128    self.start = start;
129    self
130  }
131
132  pub fn with_end(mut self, end: u64) -> Self {
133    self.end = Some(end);
134    self
135  }
136
137  pub fn set_end(mut self, end: Option<u64>) -> Self {
138    self.end = end;
139    self
140  }
141
142  pub fn with_class(mut self, class: Class) -> Self {
143    self.class = Some(class);
144    self
145  }
146
147  pub fn set_class(mut self, class: Option<Class>) -> Self {
148    self.class = class;
149    self
150  }
151
152  /// Build the bytes position, returning an error if the end is less than the start.
153  pub fn build(self) -> Result<BytesPosition> {
154    if self
155      .end
156      .is_some_and(|end| end < self.start.unwrap_or_default())
157    {
158      return Err(StorageError::InternalError(format!(
159        "invalid bytes position, end `{:?}` is less than start `{:?}`",
160        self.end, self.start
161      )));
162    }
163
164    Ok(BytesPosition {
165      start: self.start,
166      end: self.end,
167      class: self.class,
168    })
169  }
170}
171
172impl BytesPosition {
173  /// Create a builder for a bytes position.
174  pub fn builder() -> BytesPositionBuilder {
175    BytesPositionBuilder::default()
176  }
177
178  pub fn with_class(self, class: Class) -> Self {
179    self.set_class(Some(class))
180  }
181
182  pub fn set_class(mut self, class: Option<Class>) -> Self {
183    self.class = class;
184    self
185  }
186
187  pub fn get_start(&self) -> Option<u64> {
188    self.start
189  }
190
191  pub fn get_end(&self) -> Option<u64> {
192    self.end
193  }
194
195  pub fn get_class(&self) -> Option<Class> {
196    self.class
197  }
198
199  /// Check whether this position selects no bytes, i.e. the end == start.
200  pub fn is_empty(&self) -> bool {
201    self
202      .end
203      .is_some_and(|end| end == self.start.unwrap_or_default())
204  }
205
206  pub fn overlaps(&self, range: &BytesPosition) -> bool {
207    let cond1 = match (self.start.as_ref(), range.end.as_ref()) {
208      (None, None) | (None, Some(_)) | (Some(_), None) => true,
209      (Some(start), Some(end)) => end >= start,
210    };
211    let cond2 = match (self.end.as_ref(), range.start.as_ref()) {
212      (None, None) | (None, Some(_)) | (Some(_), None) => true,
213      (Some(end), Some(start)) => end >= start,
214    };
215    cond1 && cond2
216  }
217
218  /// Merges position with the current BytesPosition, assuming that the two positions overlap.
219  pub fn merge_with(&mut self, position: &BytesPosition) -> &Self {
220    let start = self.start;
221    let end = self.end;
222
223    self.start = match (start.as_ref(), position.start.as_ref()) {
224      (None, None) | (None, Some(_)) | (Some(_), None) => None,
225      (Some(a), Some(b)) => Some(*a.min(b)),
226    };
227    self.end = match (end.as_ref(), position.end.as_ref()) {
228      (None, None) | (None, Some(_)) | (Some(_), None) => None,
229      (Some(a), Some(b)) => Some(*a.max(b)),
230    };
231
232    self.class = match (self.class.as_ref(), position.class.as_ref()) {
233      (Some(Class::Header), Some(Class::Header)) => Some(Class::Header),
234      (Some(Class::Body), Some(Class::Body)) => Some(Class::Body),
235      (_, _) => None,
236    };
237
238    self
239  }
240
241  /// Merge ranges, assuming ending byte ranges are exclusive.
242  #[instrument(level = "trace", ret)]
243  pub fn merge_all(mut ranges: Vec<BytesPosition>) -> Vec<BytesPosition> {
244    ranges.retain(|range| !range.is_empty());
245
246    if ranges.len() < 2 {
247      ranges
248    } else {
249      ranges.sort_by(|a, b| {
250        let a_start = a.get_start().unwrap_or(0);
251        let b_start = b.get_start().unwrap_or(0);
252        let start_ord = a_start.cmp(&b_start);
253        if start_ord == Ordering::Equal {
254          let a_end = a.get_end().unwrap_or(u64::MAX);
255          let b_end = b.get_end().unwrap_or(u64::MAX);
256          b_end.cmp(&a_end)
257        } else {
258          start_ord
259        }
260      });
261
262      let mut optimized_ranges = Vec::with_capacity(ranges.len());
263
264      let mut current_range = ranges[0].clone();
265
266      for range in ranges.iter().skip(1) {
267        if current_range.overlaps(range) {
268          current_range.merge_with(range);
269        } else {
270          optimized_ranges.push(current_range);
271          current_range = range.clone();
272        }
273      }
274
275      optimized_ranges.push(current_range);
276
277      optimized_ranges
278    }
279  }
280}
281
282#[derive(Debug, Clone)]
283pub struct GetOptions<'a> {
284  pub(crate) range: BytesPosition,
285  pub(crate) request_headers: Cow<'a, HeaderMap>,
286}
287
288impl<'a> GetOptions<'a> {
289  pub fn new(range: BytesPosition, request_headers: &'a HeaderMap) -> Self {
290    Self {
291      range,
292      request_headers: Cow::Borrowed(request_headers),
293    }
294  }
295
296  pub fn new_with_default_range(request_headers: &'a HeaderMap) -> Self {
297    Self::new(Default::default(), request_headers)
298  }
299
300  pub fn with_max_length(mut self, max_length: u64) -> Result<Self> {
301    self.range = BytesPosition::builder()
302      .with_start(0)
303      .with_end(max_length)
304      .build()?;
305    Ok(self)
306  }
307
308  pub fn with_range(mut self, range: BytesPosition) -> Self {
309    self.range = range;
310    self
311  }
312
313  /// Get the range.
314  pub fn range(&self) -> &BytesPosition {
315    &self.range
316  }
317
318  /// Get the request headers.
319  pub fn request_headers(&self) -> &HeaderMap {
320    self.request_headers.as_ref()
321  }
322
323  /// Set the request headers from an owned value.
324  pub fn set_request_headers(&mut self, request_headers: HeaderMap) {
325    self.request_headers = Cow::Owned(request_headers);
326  }
327}
328
329#[derive(Debug, Clone)]
330pub struct BytesPositionOptions<'a> {
331  pub(crate) positions: Vec<BytesPosition>,
332  pub(crate) headers: &'a HeaderMap,
333}
334
335impl<'a> BytesPositionOptions<'a> {
336  pub fn new(positions: Vec<BytesPosition>, headers: &'a HeaderMap) -> Self {
337    Self { positions, headers }
338  }
339
340  /// Get the response headers.
341  pub fn headers(&self) -> &'a HeaderMap {
342    self.headers
343  }
344
345  pub fn positions(&self) -> &Vec<BytesPosition> {
346    &self.positions
347  }
348
349  /// Get the inner value.
350  pub fn into_inner(self) -> Vec<BytesPosition> {
351    self.positions
352  }
353
354  /// Merge all bytes positions
355  pub fn merge_all(mut self) -> Self {
356    self.positions = BytesPosition::merge_all(self.positions);
357    self
358  }
359}
360
361#[derive(Debug, Clone)]
362pub struct RangeUrlOptions<'a> {
363  range: BytesPosition,
364  response_headers: &'a HeaderMap,
365}
366
367impl<'a> RangeUrlOptions<'a> {
368  pub fn new(range: BytesPosition, response_headers: &'a HeaderMap) -> Self {
369    Self {
370      range,
371      response_headers,
372    }
373  }
374
375  pub fn new_with_default_range(request_headers: &'a HeaderMap) -> Self {
376    Self::new(Default::default(), request_headers)
377  }
378
379  pub fn with_range(mut self, range: BytesPosition) -> Self {
380    self.range = range;
381    self
382  }
383
384  pub fn apply(self, url: Url) -> Result<Url> {
385    let range: String = String::from(&BytesRange::try_from(self.range())?);
386
387    let url = if range.is_empty() {
388      url
389    } else {
390      url.add_headers(Headers::default().with_header("Range", range))
391    };
392
393    Ok(url.set_class(self.range().class))
394  }
395
396  /// Get the range.
397  pub fn range(&self) -> &BytesPosition {
398    &self.range
399  }
400
401  /// Get the response headers.
402  pub fn response_headers(&self) -> &'a HeaderMap {
403    self.response_headers
404  }
405}
406
407/// A struct to represent options passed to a `Storage` head call.
408#[derive(Debug, Clone)]
409pub struct HeadOptions<'a> {
410  request_headers: &'a HeaderMap,
411}
412
413impl<'a> HeadOptions<'a> {
414  /// Create a new HeadOptions struct.
415  pub fn new(request_headers: &'a HeaderMap) -> Self {
416    Self { request_headers }
417  }
418
419  /// Get the request headers.
420  pub fn request_headers(&self) -> &'a HeaderMap {
421    self.request_headers
422  }
423}
424
425impl<'a> From<&'a GetOptions<'a>> for HeadOptions<'a> {
426  fn from(options: &'a GetOptions<'a>) -> Self {
427    Self::new(options.request_headers())
428  }
429}
430
431#[cfg(test)]
432mod tests {
433  use std::collections::HashMap;
434
435  use super::*;
436
437  #[test]
438  fn bytes_range_overlapping_and_merge() {
439    let test_cases = vec![
440      (
441        BytesPosition::builder().with_end(2).build().unwrap(),
442        BytesPosition::builder()
443          .with_start(3)
444          .with_end(5)
445          .build()
446          .unwrap(),
447        None,
448      ),
449      (
450        BytesPosition::builder().with_end(2).build().unwrap(),
451        BytesPosition::builder().with_start(3).build().unwrap(),
452        None,
453      ),
454      (
455        BytesPosition::builder().with_end(2).build().unwrap(),
456        BytesPosition::builder()
457          .with_start(2)
458          .with_end(4)
459          .build()
460          .unwrap(),
461        Some(BytesPosition::builder().with_end(4).build().unwrap()),
462      ),
463      (
464        BytesPosition::builder().with_end(2).build().unwrap(),
465        BytesPosition::builder().with_start(2).build().unwrap(),
466        Some(BytesPosition::builder().build().unwrap()),
467      ),
468      (
469        BytesPosition::builder().with_end(2).build().unwrap(),
470        BytesPosition::builder()
471          .with_start(1)
472          .with_end(3)
473          .build()
474          .unwrap(),
475        Some(BytesPosition::builder().with_end(3).build().unwrap()),
476      ),
477      (
478        BytesPosition::builder().with_end(2).build().unwrap(),
479        BytesPosition::builder().with_start(1).build().unwrap(),
480        Some(BytesPosition::builder().build().unwrap()),
481      ),
482      (
483        BytesPosition::builder().with_end(2).build().unwrap(),
484        BytesPosition::builder()
485          .with_start(0)
486          .with_end(2)
487          .build()
488          .unwrap(),
489        Some(BytesPosition::builder().with_end(2).build().unwrap()),
490      ),
491      (
492        BytesPosition::builder().with_end(2).build().unwrap(),
493        BytesPosition::builder().with_end(2).build().unwrap(),
494        Some(BytesPosition::builder().with_end(2).build().unwrap()),
495      ),
496      (
497        BytesPosition::builder().with_end(2).build().unwrap(),
498        BytesPosition::builder()
499          .with_start(0)
500          .with_end(1)
501          .build()
502          .unwrap(),
503        Some(BytesPosition::builder().with_end(2).build().unwrap()),
504      ),
505      (
506        BytesPosition::builder().with_end(2).build().unwrap(),
507        BytesPosition::builder().with_end(1).build().unwrap(),
508        Some(BytesPosition::builder().with_end(2).build().unwrap()),
509      ),
510      (
511        BytesPosition::builder().with_end(2).build().unwrap(),
512        BytesPosition::builder().build().unwrap(),
513        Some(BytesPosition::builder().build().unwrap()),
514      ),
515      (
516        BytesPosition::builder()
517          .with_start(2)
518          .with_end(4)
519          .build()
520          .unwrap(),
521        BytesPosition::builder()
522          .with_start(6)
523          .with_end(8)
524          .build()
525          .unwrap(),
526        None,
527      ),
528      (
529        BytesPosition::builder()
530          .with_start(2)
531          .with_end(4)
532          .build()
533          .unwrap(),
534        BytesPosition::builder().with_start(6).build().unwrap(),
535        None,
536      ),
537      (
538        BytesPosition::builder()
539          .with_start(2)
540          .with_end(4)
541          .build()
542          .unwrap(),
543        BytesPosition::builder()
544          .with_start(4)
545          .with_end(6)
546          .build()
547          .unwrap(),
548        Some(
549          BytesPosition::builder()
550            .with_start(2)
551            .with_end(6)
552            .build()
553            .unwrap(),
554        ),
555      ),
556      (
557        BytesPosition::builder()
558          .with_start(2)
559          .with_end(4)
560          .build()
561          .unwrap(),
562        BytesPosition::builder().with_start(4).build().unwrap(),
563        Some(BytesPosition::builder().with_start(2).build().unwrap()),
564      ),
565      (
566        BytesPosition::builder()
567          .with_start(2)
568          .with_end(4)
569          .build()
570          .unwrap(),
571        BytesPosition::builder()
572          .with_start(3)
573          .with_end(5)
574          .build()
575          .unwrap(),
576        Some(
577          BytesPosition::builder()
578            .with_start(2)
579            .with_end(5)
580            .build()
581            .unwrap(),
582        ),
583      ),
584      (
585        BytesPosition::builder()
586          .with_start(2)
587          .with_end(4)
588          .build()
589          .unwrap(),
590        BytesPosition::builder().with_start(3).build().unwrap(),
591        Some(BytesPosition::builder().with_start(2).build().unwrap()),
592      ),
593      (
594        BytesPosition::builder()
595          .with_start(2)
596          .with_end(4)
597          .build()
598          .unwrap(),
599        BytesPosition::builder()
600          .with_start(2)
601          .with_end(3)
602          .build()
603          .unwrap(),
604        Some(
605          BytesPosition::builder()
606            .with_start(2)
607            .with_end(4)
608            .build()
609            .unwrap(),
610        ),
611      ),
612      (
613        BytesPosition::builder()
614          .with_start(2)
615          .with_end(4)
616          .build()
617          .unwrap(),
618        BytesPosition::builder().with_end(3).build().unwrap(),
619        Some(BytesPosition::builder().with_end(4).build().unwrap()),
620      ),
621      (
622        BytesPosition::builder()
623          .with_start(2)
624          .with_end(4)
625          .build()
626          .unwrap(),
627        BytesPosition::builder()
628          .with_start(1)
629          .with_end(3)
630          .build()
631          .unwrap(),
632        Some(
633          BytesPosition::builder()
634            .with_start(1)
635            .with_end(4)
636            .build()
637            .unwrap(),
638        ),
639      ),
640      (
641        BytesPosition::builder()
642          .with_start(2)
643          .with_end(4)
644          .build()
645          .unwrap(),
646        BytesPosition::builder().with_end(3).build().unwrap(),
647        Some(BytesPosition::builder().with_end(4).build().unwrap()),
648      ),
649      (
650        BytesPosition::builder()
651          .with_start(2)
652          .with_end(4)
653          .build()
654          .unwrap(),
655        BytesPosition::builder()
656          .with_start(0)
657          .with_end(2)
658          .build()
659          .unwrap(),
660        Some(
661          BytesPosition::builder()
662            .with_start(0)
663            .with_end(4)
664            .build()
665            .unwrap(),
666        ),
667      ),
668      (
669        BytesPosition::builder()
670          .with_start(2)
671          .with_end(4)
672          .build()
673          .unwrap(),
674        BytesPosition::builder().with_end(2).build().unwrap(),
675        Some(BytesPosition::builder().with_end(4).build().unwrap()),
676      ),
677      (
678        BytesPosition::builder()
679          .with_start(2)
680          .with_end(4)
681          .build()
682          .unwrap(),
683        BytesPosition::builder()
684          .with_start(0)
685          .with_end(1)
686          .build()
687          .unwrap(),
688        None,
689      ),
690      (
691        BytesPosition::builder()
692          .with_start(2)
693          .with_end(4)
694          .build()
695          .unwrap(),
696        BytesPosition::builder().with_end(1).build().unwrap(),
697        None,
698      ),
699      (
700        BytesPosition::builder()
701          .with_start(2)
702          .with_end(4)
703          .build()
704          .unwrap(),
705        BytesPosition::builder().build().unwrap(),
706        Some(BytesPosition::builder().build().unwrap()),
707      ),
708      (
709        BytesPosition::builder().with_start(2).build().unwrap(),
710        BytesPosition::builder()
711          .with_start(4)
712          .with_end(6)
713          .build()
714          .unwrap(),
715        Some(BytesPosition::builder().with_start(2).build().unwrap()),
716      ),
717      (
718        BytesPosition::builder().with_start(2).build().unwrap(),
719        BytesPosition::builder().with_start(4).build().unwrap(),
720        Some(BytesPosition::builder().with_start(2).build().unwrap()),
721      ),
722      (
723        BytesPosition::builder().with_start(2).build().unwrap(),
724        BytesPosition::builder()
725          .with_start(2)
726          .with_end(4)
727          .build()
728          .unwrap(),
729        Some(BytesPosition::builder().with_start(2).build().unwrap()),
730      ),
731      (
732        BytesPosition::builder().with_start(2).build().unwrap(),
733        BytesPosition::builder().with_start(2).build().unwrap(),
734        Some(BytesPosition::builder().with_start(2).build().unwrap()),
735      ),
736      (
737        BytesPosition::builder().with_start(2).build().unwrap(),
738        BytesPosition::builder()
739          .with_start(1)
740          .with_end(3)
741          .build()
742          .unwrap(),
743        Some(BytesPosition::builder().with_start(1).build().unwrap()),
744      ),
745      (
746        BytesPosition::builder().with_start(2).build().unwrap(),
747        BytesPosition::builder().with_end(3).build().unwrap(),
748        Some(BytesPosition::builder().build().unwrap()),
749      ),
750      (
751        BytesPosition::builder().with_start(2).build().unwrap(),
752        BytesPosition::builder()
753          .with_start(0)
754          .with_end(2)
755          .build()
756          .unwrap(),
757        Some(BytesPosition::builder().with_start(0).build().unwrap()),
758      ),
759      (
760        BytesPosition::builder().with_start(2).build().unwrap(),
761        BytesPosition::builder().with_end(2).build().unwrap(),
762        Some(BytesPosition::builder().build().unwrap()),
763      ),
764      (
765        BytesPosition::builder().with_start(2).build().unwrap(),
766        BytesPosition::builder()
767          .with_start(0)
768          .with_end(1)
769          .build()
770          .unwrap(),
771        None,
772      ),
773      (
774        BytesPosition::builder().with_start(2).build().unwrap(),
775        BytesPosition::builder().with_end(1).build().unwrap(),
776        None,
777      ),
778      (
779        BytesPosition::builder().with_start(2).build().unwrap(),
780        BytesPosition::builder().build().unwrap(),
781        Some(BytesPosition::builder().build().unwrap()),
782      ),
783      (
784        BytesPosition::builder().build().unwrap(),
785        BytesPosition::builder().build().unwrap(),
786        Some(BytesPosition::builder().build().unwrap()),
787      ),
788    ];
789
790    for (index, (a, b, expected)) in test_cases.iter().enumerate() {
791      println!("Test case {index}");
792      println!("  {a:?}");
793      println!("  {b:?}");
794      println!("  {expected:?}");
795
796      if a.overlaps(b) {
797        assert_eq!(*a.clone().merge_with(b), expected.clone().unwrap());
798      } else {
799        assert!(expected.is_none())
800      }
801    }
802  }
803
804  #[test]
805  fn bytes_range_merge_all_when_list_is_empty() {
806    assert_eq!(BytesPosition::merge_all(Vec::new()), Vec::new());
807  }
808
809  #[test]
810  fn bytes_range_merge_all_removes_empty_positions() {
811    assert_eq!(
812      BytesPosition::merge_all(vec![
813        BytesPosition::builder()
814          .with_start(0)
815          .with_end(0)
816          .build()
817          .unwrap(),
818        BytesPosition::builder()
819          .with_start(5)
820          .with_end(5)
821          .build()
822          .unwrap(),
823        BytesPosition::builder()
824          .with_start(1)
825          .with_end(2)
826          .build()
827          .unwrap(),
828      ]),
829      vec![
830        BytesPosition::builder()
831          .with_start(1)
832          .with_end(2)
833          .build()
834          .unwrap()
835      ]
836    );
837  }
838
839  #[test]
840  fn bytes_position_is_empty() {
841    assert!(
842      BytesPosition::builder()
843        .with_start(0)
844        .with_end(0)
845        .build()
846        .unwrap()
847        .is_empty()
848    );
849    assert!(
850      BytesPosition::builder()
851        .with_end(0)
852        .build()
853        .unwrap()
854        .is_empty()
855    );
856    assert!(
857      !BytesPosition::builder()
858        .with_start(0)
859        .with_end(1)
860        .build()
861        .unwrap()
862        .is_empty()
863    );
864    assert!(
865      !BytesPosition::builder()
866        .with_start(1)
867        .build()
868        .unwrap()
869        .is_empty()
870    );
871    assert!(!BytesPosition::builder().build().unwrap().is_empty());
872  }
873
874  #[test]
875  fn bytes_position_end_less_than_start() {
876    assert!(
877      BytesPosition::builder()
878        .with_start(2)
879        .with_end(1)
880        .build()
881        .is_err()
882    );
883    assert!(BytesPosition::builder().with_end(1).build().is_ok());
884    assert!(
885      BytesPosition::builder()
886        .with_end(2)
887        .with_start(3)
888        .build()
889        .is_err()
890    );
891    assert!(
892      BytesPosition::builder()
893        .with_start(3)
894        .with_end(2)
895        .build()
896        .is_err()
897    );
898    assert!(
899      BytesPosition::builder()
900        .with_start(3)
901        .set_end(Some(2))
902        .build()
903        .is_err()
904    );
905  }
906
907  #[test]
908  fn bytes_position_builder() {
909    let result = BytesPosition::builder()
910      .with_end(2)
911      .with_start(5)
912      .with_end(10)
913      .build();
914    assert_eq!(
915      result.unwrap(),
916      BytesPosition::builder()
917        .with_start(5)
918        .with_end(10)
919        .build()
920        .unwrap()
921    );
922  }
923
924  #[test]
925  fn bytes_range_try_from_empty_position() {
926    assert!(
927      BytesRange::try_from(
928        &BytesPosition::builder()
929          .with_start(5)
930          .with_end(5)
931          .build()
932          .unwrap()
933      )
934      .is_err()
935    );
936    assert!(BytesRange::try_from(&BytesPosition::builder().with_end(0).build().unwrap()).is_err());
937  }
938
939  #[test]
940  fn bytes_range_merge_all_when_list_has_one_range() {
941    assert_eq!(
942      BytesPosition::merge_all(vec![BytesPosition::default()]),
943      vec![BytesPosition::default()]
944    );
945  }
946
947  #[test]
948  fn bytes_position_merge_class_header() {
949    assert_eq!(
950      BytesPosition::merge_all(vec![
951        BytesPosition::builder()
952          .with_end(1)
953          .with_class(Class::Header)
954          .build()
955          .unwrap(),
956        BytesPosition::builder()
957          .with_end(2)
958          .with_class(Class::Header)
959          .build()
960          .unwrap()
961      ]),
962      vec![
963        BytesPosition::builder()
964          .with_end(2)
965          .with_class(Class::Header)
966          .build()
967          .unwrap()
968      ]
969    );
970  }
971
972  #[test]
973  fn bytes_position_merge_class_body() {
974    assert_eq!(
975      BytesPosition::merge_all(vec![
976        BytesPosition::builder()
977          .with_end(1)
978          .with_class(Class::Body)
979          .build()
980          .unwrap(),
981        BytesPosition::builder()
982          .with_end(3)
983          .with_class(Class::Body)
984          .build()
985          .unwrap()
986      ]),
987      vec![
988        BytesPosition::builder()
989          .with_end(3)
990          .with_class(Class::Body)
991          .build()
992          .unwrap()
993      ]
994    );
995  }
996
997  #[test]
998  fn bytes_position_merge_class_none() {
999    assert_eq!(
1000      BytesPosition::merge_all(vec![
1001        BytesPosition::builder()
1002          .with_start(1)
1003          .with_end(2)
1004          .build()
1005          .unwrap(),
1006        BytesPosition::builder()
1007          .with_start(2)
1008          .with_end(3)
1009          .build()
1010          .unwrap()
1011      ]),
1012      vec![
1013        BytesPosition::builder()
1014          .with_start(1)
1015          .with_end(3)
1016          .build()
1017          .unwrap()
1018      ]
1019    );
1020  }
1021
1022  #[test]
1023  fn bytes_position_merge_class_different() {
1024    assert_eq!(
1025      BytesPosition::merge_all(vec![
1026        BytesPosition::builder()
1027          .with_start(1)
1028          .with_end(2)
1029          .with_class(Class::Header)
1030          .build()
1031          .unwrap(),
1032        BytesPosition::builder()
1033          .with_start(2)
1034          .with_end(3)
1035          .with_class(Class::Body)
1036          .build()
1037          .unwrap()
1038      ]),
1039      vec![
1040        BytesPosition::builder()
1041          .with_start(1)
1042          .with_end(3)
1043          .build()
1044          .unwrap()
1045      ]
1046    );
1047  }
1048
1049  #[test]
1050  fn bytes_range_merge_all_when_list_has_many_ranges() {
1051    let ranges = vec![
1052      BytesPosition::builder().with_end(1).build().unwrap(),
1053      BytesPosition::builder()
1054        .with_start(1)
1055        .with_end(2)
1056        .build()
1057        .unwrap(),
1058      BytesPosition::builder()
1059        .with_start(5)
1060        .with_end(6)
1061        .build()
1062        .unwrap(),
1063      BytesPosition::builder()
1064        .with_start(5)
1065        .with_end(8)
1066        .build()
1067        .unwrap(),
1068      BytesPosition::builder()
1069        .with_start(6)
1070        .with_end(7)
1071        .build()
1072        .unwrap(),
1073      BytesPosition::builder()
1074        .with_start(4)
1075        .with_end(5)
1076        .build()
1077        .unwrap(),
1078      BytesPosition::builder()
1079        .with_start(3)
1080        .with_end(6)
1081        .build()
1082        .unwrap(),
1083      BytesPosition::builder()
1084        .with_start(10)
1085        .with_end(12)
1086        .build()
1087        .unwrap(),
1088      BytesPosition::builder()
1089        .with_start(10)
1090        .with_end(12)
1091        .build()
1092        .unwrap(),
1093      BytesPosition::builder()
1094        .with_start(10)
1095        .with_end(14)
1096        .build()
1097        .unwrap(),
1098      BytesPosition::builder()
1099        .with_start(14)
1100        .with_end(15)
1101        .build()
1102        .unwrap(),
1103      BytesPosition::builder()
1104        .with_start(12)
1105        .with_end(16)
1106        .build()
1107        .unwrap(),
1108      BytesPosition::builder()
1109        .with_start(17)
1110        .with_end(19)
1111        .build()
1112        .unwrap(),
1113      BytesPosition::builder()
1114        .with_start(21)
1115        .with_end(23)
1116        .build()
1117        .unwrap(),
1118      BytesPosition::builder()
1119        .with_start(18)
1120        .with_end(22)
1121        .build()
1122        .unwrap(),
1123      BytesPosition::builder().with_start(24).build().unwrap(),
1124      BytesPosition::builder()
1125        .with_start(24)
1126        .with_end(30)
1127        .build()
1128        .unwrap(),
1129      BytesPosition::builder()
1130        .with_start(31)
1131        .with_end(33)
1132        .build()
1133        .unwrap(),
1134      BytesPosition::builder().with_start(35).build().unwrap(),
1135    ];
1136
1137    let expected_ranges = vec![
1138      BytesPosition::builder().with_end(2).build().unwrap(),
1139      BytesPosition::builder()
1140        .with_start(3)
1141        .with_end(8)
1142        .build()
1143        .unwrap(),
1144      BytesPosition::builder()
1145        .with_start(10)
1146        .with_end(16)
1147        .build()
1148        .unwrap(),
1149      BytesPosition::builder()
1150        .with_start(17)
1151        .with_end(23)
1152        .build()
1153        .unwrap(),
1154      BytesPosition::builder().with_start(24).build().unwrap(),
1155    ];
1156
1157    assert_eq!(BytesPosition::merge_all(ranges), expected_ranges);
1158  }
1159
1160  #[test]
1161  fn bytes_position_new() {
1162    let result = BytesPosition::builder()
1163      .with_start(1)
1164      .with_end(2)
1165      .with_class(Class::Header)
1166      .build()
1167      .unwrap();
1168    assert_eq!(result.start, Some(1));
1169    assert_eq!(result.end, Some(2));
1170    assert_eq!(result.class, Some(Class::Header));
1171  }
1172
1173  #[test]
1174  fn bytes_position_with_start() {
1175    let result = BytesPosition::builder().with_start(1).build().unwrap();
1176    assert_eq!(result.start, Some(1));
1177  }
1178
1179  #[test]
1180  fn bytes_position_with_end() {
1181    let result = BytesPosition::builder().with_end(1).build().unwrap();
1182    assert_eq!(result.end, Some(1));
1183  }
1184
1185  #[test]
1186  fn bytes_position_with_class() {
1187    let result = BytesPosition::default().with_class(Class::Header);
1188    assert_eq!(result.class, Some(Class::Header));
1189  }
1190
1191  #[test]
1192  fn bytes_position_set_class() {
1193    let result = BytesPosition::default().set_class(Some(Class::Header));
1194    assert_eq!(result.class, Some(Class::Header));
1195  }
1196
1197  #[test]
1198  fn data_block_update_classes_all_some() {
1199    let blocks = DataBlock::update_classes(vec![
1200      DataBlock::Range(
1201        BytesPosition::builder()
1202          .with_end(1)
1203          .with_class(Class::Body)
1204          .build()
1205          .unwrap(),
1206      ),
1207      DataBlock::Data(vec![], Some(Class::Header)),
1208    ]);
1209    for block in blocks {
1210      let class = match block {
1211        DataBlock::Range(pos) => pos.class,
1212        DataBlock::Data(_, class) => class,
1213      };
1214      assert!(class.is_some());
1215    }
1216  }
1217
1218  #[test]
1219  fn data_block_update_classes_one_none() {
1220    let blocks = DataBlock::update_classes(vec![
1221      DataBlock::Range(
1222        BytesPosition::builder()
1223          .with_end(1)
1224          .with_class(Class::Body)
1225          .build()
1226          .unwrap(),
1227      ),
1228      DataBlock::Data(vec![], None),
1229    ]);
1230    for block in blocks {
1231      let class = match block {
1232        DataBlock::Range(pos) => pos.class,
1233        DataBlock::Data(_, class) => class,
1234      };
1235      assert!(class.is_none());
1236    }
1237  }
1238
1239  #[test]
1240  fn data_block_from_bytes_positions() {
1241    let blocks = DataBlock::from_bytes_positions(vec![
1242      BytesPosition::builder().with_end(1).build().unwrap(),
1243      BytesPosition::builder()
1244        .with_start(1)
1245        .with_end(2)
1246        .build()
1247        .unwrap(),
1248    ]);
1249    assert_eq!(
1250      blocks,
1251      vec![DataBlock::Range(
1252        BytesPosition::builder().with_end(2).build().unwrap()
1253      )]
1254    );
1255  }
1256
1257  #[test]
1258  fn data_block_from_empty_bytes_positions() {
1259    let blocks = DataBlock::from_bytes_positions(vec![
1260      BytesPosition::builder()
1261        .with_start(0)
1262        .with_end(0)
1263        .build()
1264        .unwrap(),
1265    ]);
1266    assert_eq!(blocks, vec![]);
1267  }
1268
1269  #[test]
1270  fn data_block_is_empty() {
1271    assert!(
1272      DataBlock::Range(
1273        BytesPosition::builder()
1274          .with_start(0)
1275          .with_end(0)
1276          .build()
1277          .unwrap()
1278      )
1279      .is_empty()
1280    );
1281    assert!(DataBlock::Data(vec![], None).is_empty());
1282    assert!(
1283      !DataBlock::Range(
1284        BytesPosition::builder()
1285          .with_start(0)
1286          .with_end(1)
1287          .build()
1288          .unwrap()
1289      )
1290      .is_empty()
1291    );
1292    assert!(!DataBlock::Data(vec![0], None).is_empty());
1293  }
1294
1295  #[test]
1296  fn byte_range_from_byte_position() {
1297    let result = BytesRange::try_from(
1298      &BytesPosition::builder()
1299        .with_start(5)
1300        .with_end(10)
1301        .build()
1302        .unwrap(),
1303    )
1304    .unwrap();
1305    let expected = BytesRange::new(Some(5), Some(9));
1306    assert_eq!(result, expected);
1307  }
1308
1309  #[test]
1310  fn get_options_with_max_length() {
1311    let request_headers = Default::default();
1312    let result = GetOptions::new_with_default_range(&request_headers)
1313      .with_max_length(1)
1314      .unwrap();
1315    assert_eq!(
1316      result.range(),
1317      &BytesPosition::builder()
1318        .with_start(0)
1319        .with_end(1)
1320        .build()
1321        .unwrap()
1322    );
1323  }
1324
1325  #[test]
1326  fn get_options_with_range() {
1327    let request_headers = Default::default();
1328    let result = GetOptions::new_with_default_range(&request_headers).with_range(
1329      BytesPosition::builder()
1330        .with_start(5)
1331        .with_end(11)
1332        .with_class(Class::Header)
1333        .build()
1334        .unwrap(),
1335    );
1336    assert_eq!(
1337      result.range(),
1338      &BytesPosition::builder()
1339        .with_start(5)
1340        .with_end(11)
1341        .with_class(Class::Header)
1342        .build()
1343        .unwrap()
1344    );
1345  }
1346
1347  #[test]
1348  fn url_options_with_range() {
1349    let request_headers = Default::default();
1350    let result = RangeUrlOptions::new_with_default_range(&request_headers).with_range(
1351      BytesPosition::builder()
1352        .with_start(5)
1353        .with_end(11)
1354        .with_class(Class::Header)
1355        .build()
1356        .unwrap(),
1357    );
1358    assert_eq!(
1359      result.range(),
1360      &BytesPosition::builder()
1361        .with_start(5)
1362        .with_end(11)
1363        .with_class(Class::Header)
1364        .build()
1365        .unwrap()
1366    );
1367  }
1368
1369  #[test]
1370  fn url_options_apply_with_bytes_range() {
1371    let result = RangeUrlOptions::new(
1372      BytesPosition::builder()
1373        .with_start(5)
1374        .with_end(11)
1375        .with_class(Class::Header)
1376        .build()
1377        .unwrap(),
1378      &Default::default(),
1379    )
1380    .apply(Url::new(""))
1381    .unwrap();
1382    println!("{result:?}");
1383    assert_eq!(
1384      result,
1385      Url::new("")
1386        .with_headers(Headers::new(HashMap::new()).with_header("Range", "bytes=5-10"))
1387        .with_class(Class::Header)
1388    );
1389  }
1390
1391  #[test]
1392  fn url_options_apply_no_bytes_range() {
1393    let result = RangeUrlOptions::new_with_default_range(&Default::default())
1394      .apply(Url::new(""))
1395      .unwrap();
1396    assert_eq!(result, Url::new(""));
1397  }
1398
1399  #[test]
1400  fn url_options_apply_with_headers() {
1401    let result = RangeUrlOptions::new(
1402      BytesPosition::builder()
1403        .with_start(5)
1404        .with_end(11)
1405        .with_class(Class::Header)
1406        .build()
1407        .unwrap(),
1408      &Default::default(),
1409    )
1410    .apply(Url::new("").with_headers(Headers::default().with_header("header", "value")))
1411    .unwrap();
1412    println!("{result:?}");
1413
1414    assert_eq!(
1415      result,
1416      Url::new("")
1417        .with_headers(
1418          Headers::new(HashMap::new())
1419            .with_header("Range", "bytes=5-10")
1420            .with_header("header", "value")
1421        )
1422        .with_class(Class::Header)
1423    );
1424  }
1425}