ndhistogram/axis/bininterval/
bininterval.rs1use std::{
2 convert::TryFrom,
3 error::Error,
4 fmt::{Display, LowerExp, UpperExp},
5 ops::{Range, RangeFrom, RangeTo},
6};
7
8#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
10pub enum BinInterval<T> {
11 Underflow {
14 end: T,
16 },
17 Overflow {
20 start: T,
22 },
23 Bin {
27 start: T,
29 end: T,
31 },
32}
33
34impl<T> BinInterval<T> {
35 pub fn underflow(end: T) -> Self {
37 Self::Underflow { end }
38 }
39 pub fn overflow(start: T) -> Self {
41 Self::Overflow { start }
42 }
43 pub fn new(start: T, end: T) -> Self {
45 Self::Bin { start, end }
46 }
47}
48
49impl<T: Copy> BinInterval<T> {
50 pub fn start(&self) -> Option<T> {
54 match self {
55 Self::Underflow { end: _ } => None,
56 Self::Overflow { start } => Some(*start),
57 Self::Bin { start, end: _ } => Some(*start),
58 }
59 }
60
61 pub fn end(&self) -> Option<T> {
65 match self {
66 Self::Underflow { end } => Some(*end),
67 Self::Overflow { start: _ } => None,
68 Self::Bin { start: _, end } => Some(*end),
69 }
70 }
71}
72
73impl<T> From<Range<T>> for BinInterval<T> {
74 fn from(other: Range<T>) -> Self {
75 Self::Bin {
76 start: other.start,
77 end: other.end,
78 }
79 }
80}
81
82impl<T> From<RangeTo<T>> for BinInterval<T> {
83 fn from(other: RangeTo<T>) -> Self {
84 Self::Underflow { end: other.end }
85 }
86}
87
88impl<T> From<RangeFrom<T>> for BinInterval<T> {
89 fn from(other: RangeFrom<T>) -> Self {
90 Self::Overflow { start: other.start }
91 }
92}
93
94impl<T> TryFrom<BinInterval<T>> for Range<T> {
95 type Error = BinIntervalConversionError;
96
97 fn try_from(value: BinInterval<T>) -> Result<Self, Self::Error> {
98 if let BinInterval::Bin { start, end } = value {
99 return Ok(Self { start, end });
100 }
101 Err(BinIntervalConversionError)
102 }
103}
104
105impl<T> TryFrom<BinInterval<T>> for RangeTo<T> {
106 type Error = BinIntervalConversionError;
107
108 fn try_from(value: BinInterval<T>) -> Result<Self, Self::Error> {
109 if let BinInterval::Underflow { end } = value {
110 return Ok(Self { end });
111 }
112 Err(BinIntervalConversionError)
113 }
114}
115
116impl<T> TryFrom<BinInterval<T>> for RangeFrom<T> {
117 type Error = BinIntervalConversionError;
118
119 fn try_from(value: BinInterval<T>) -> Result<Self, Self::Error> {
120 if let BinInterval::Overflow { start } = value {
121 return Ok(Self { start });
122 }
123 Err(BinIntervalConversionError)
124 }
125}
126
127macro_rules! impl_display {
128 ($Trait:ident) => {
129 impl<T: $Trait> $Trait for BinInterval<T> {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 match self {
132 Self::Underflow { end } => {
133 write!(f, "(-inf, ")?;
135 end.fmt(f)?;
136 write!(f, ")")?;
137 }
138 Self::Overflow { start } => {
139 write!(f, "[")?;
141 start.fmt(f)?;
142 write!(f, ", inf)")?;
143 }
144 Self::Bin { start, end } => {
145 write!(f, "[")?;
147 start.fmt(f)?;
148 write!(f, ", ")?;
149 end.fmt(f)?;
150 write!(f, ")")?;
151 }
152 }
153 Ok(())
154 }
155 }
156 };
157}
158
159impl_display! {Display}
160impl_display! {LowerExp}
161impl_display! {UpperExp}
162
163#[derive(Debug)]
164pub struct BinIntervalConversionError;
165
166impl Display for BinIntervalConversionError {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 write!(f, "invalid range to bin interval conversion")
169 }
170}
171
172impl Error for BinIntervalConversionError {}