grass_runtime/property/
region.rs1use crate::ChrRef;
2
3pub trait RegionCore {
4 fn start(&self) -> u32;
5 fn end(&self) -> u32;
6 fn chrom(&self) -> ChrRef<'static>;
7
8 #[inline(always)]
9 fn empty(&self) -> bool {
10 self.end() <= self.start()
11 }
12
13 #[inline(always)]
14 fn length(&self) -> u32 {
15 self.end().max(self.start()) - self.start()
16 }
17}
18
19impl<'a> RegionCore for (ChrRef<'a>, u32, u32) {
20 fn start(&self) -> u32 {
21 self.1
22 }
23 fn end(&self) -> u32 {
24 self.2
25 }
26 fn chrom(&self) -> ChrRef<'static> {
27 self.0.to_static()
28 }
29}
30
31pub trait Region: RegionCore {
32 #[inline(always)]
33 fn overlaps(&self, b: &impl Region) -> bool {
34 let a = self;
35 if a.chrom() != b.chrom() {
36 return false;
37 }
38
39 !(a.end() <= b.start() || b.end() <= a.start())
40 }
41}
42
43impl<T: RegionCore> Region for T {}
44
45impl<T: Region> RegionCore for Option<T> {
46 #[inline(always)]
47 fn start(&self) -> u32 {
48 self.as_ref().map_or(0, |what| what.start())
49 }
50 #[inline(always)]
51 fn end(&self) -> u32 {
52 self.as_ref().map_or(0, |what| what.end())
53 }
54 #[inline(always)]
55 fn chrom(&self) -> ChrRef<'static> {
56 self.as_ref().map_or(ChrRef::Dummy, |what| what.chrom())
57 }
58}
59
60impl<'a, T: Region> RegionCore for &'a T {
61 #[inline(always)]
62 fn start(&self) -> u32 {
63 T::start(*self)
64 }
65 #[inline(always)]
66 fn end(&self) -> u32 {
67 T::end(*self)
68 }
69 #[inline(always)]
70 fn chrom(&self) -> ChrRef<'static> {
71 T::chrom(*self)
72 }
73}
74
75impl<A: Region, B: Region> RegionCore for (A, B) {
76 #[inline(always)]
77 fn start(&self) -> u32 {
78 if self.0.overlaps(&self.1) {
79 self.0.start().max(self.1.start())
80 } else {
81 0
82 }
83 }
84
85 #[inline(always)]
86 fn end(&self) -> u32 {
87 if self.0.overlaps(&self.1) {
88 self.0.end().min(self.1.end())
89 } else {
90 0
91 }
92 }
93
94 #[inline(always)]
95 fn chrom(&self) -> ChrRef<'static> {
96 self.0.chrom()
97 }
98}