xbytes/
unit.rs

1use super::{
2    Int, Mode, ParseError,
3    UnitPrefix::{self, *},
4};
5use std::{
6    cmp::{Ord, Ordering},
7    fmt,
8    str::FromStr,
9};
10
11#[derive(Eq, Copy, Clone, Debug, PartialEq, PartialOrd)]
12pub enum SizeVariant {
13    Bit,
14    Byte,
15}
16
17use SizeVariant::*;
18
19// MAX 64-bit value => 2 EiB
20// MAX 128-bit value => 35184372088832 YiB
21
22#[derive(Eq, Copy, Clone, Debug, PartialEq)]
23pub struct Unit(Option<UnitPrefix>, SizeVariant);
24
25pub mod sizes {
26    use super::*;
27
28    #[rustfmt::skip]
29    pub mod noprefix {
30        use super::*;
31        pub const BIT: Unit = Unit(None, Bit);
32        pub const BYTE: Unit = Unit(None, Byte);
33    }
34
35    #[rustfmt::skip]
36    pub mod decimal {
37        use super::*;
38        pub const KILO_BIT : Unit = Unit::of(Kilo, Bit );
39        pub const MEGA_BIT : Unit = Unit::of(Mega, Bit );
40        pub const GIGA_BIT : Unit = Unit::of(Giga, Bit );
41        pub const TERA_BIT : Unit = Unit::of(Tera, Bit );
42        pub const PETA_BIT : Unit = Unit::of(Peta, Bit );
43        pub const EXA_BIT  : Unit = Unit::of(Exa , Bit );
44        pub const KILO_BYTE: Unit = Unit::of(Kilo, Byte);
45        pub const MEGA_BYTE: Unit = Unit::of(Mega, Byte);
46        pub const GIGA_BYTE: Unit = Unit::of(Giga, Byte);
47        pub const TERA_BYTE: Unit = Unit::of(Tera, Byte);
48        pub const PETA_BYTE: Unit = Unit::of(Peta, Byte);
49        pub const EXA_BYTE : Unit = Unit::of(Exa , Byte);
50        #[cfg(feature = "u128")] pub const ZETTA_BIT : Unit = Unit::of(Zetta, Bit );
51        #[cfg(feature = "u128")] pub const YOTTA_BIT : Unit = Unit::of(Yotta, Bit );
52        #[cfg(feature = "u128")] pub const ZETTA_BYTE: Unit = Unit::of(Zetta, Byte);
53        #[cfg(feature = "u128")] pub const YOTTA_BYTE: Unit = Unit::of(Yotta, Byte);
54    }
55
56    #[rustfmt::skip]
57    pub mod binary {
58        use super::*;
59        pub const KIBI_BIT : Unit = Unit::of(Kibi, Bit );
60        pub const MEBI_BIT : Unit = Unit::of(Mebi, Bit );
61        pub const GIBI_BIT : Unit = Unit::of(Gibi, Bit );
62        pub const TEBI_BIT : Unit = Unit::of(Tebi, Bit );
63        pub const PEBI_BIT : Unit = Unit::of(Pebi, Bit );
64        pub const EXBI_BIT : Unit = Unit::of(Exbi, Bit );
65        pub const KIBI_BYTE: Unit = Unit::of(Kibi, Byte);
66        pub const MEBI_BYTE: Unit = Unit::of(Mebi, Byte);
67        pub const GIBI_BYTE: Unit = Unit::of(Gibi, Byte);
68        pub const TEBI_BYTE: Unit = Unit::of(Tebi, Byte);
69        pub const PEBI_BYTE: Unit = Unit::of(Pebi, Byte);
70        pub const EXBI_BYTE: Unit = Unit::of(Exbi, Byte);
71        #[cfg(feature = "u128")] pub const ZEBI_BIT : Unit = Unit::of(Zebi, Bit );
72        #[cfg(feature = "u128")] pub const YOBI_BIT : Unit = Unit::of(Yobi, Bit );
73        #[cfg(feature = "u128")] pub const ZEBI_BYTE: Unit = Unit::of(Zebi, Byte);
74        #[cfg(feature = "u128")] pub const YOBI_BYTE: Unit = Unit::of(Yobi, Byte);
75    }
76
77    pub use {binary::*, decimal::*, noprefix::*};
78
79    #[rustfmt::skip]
80    pub mod bits {
81        pub use super::{
82            BIT,
83            KILO_BIT, KIBI_BIT, MEGA_BIT, MEBI_BIT, GIGA_BIT, GIBI_BIT,
84            TERA_BIT, TEBI_BIT, PETA_BIT, PEBI_BIT, EXA_BIT, EXBI_BIT,
85        };
86
87        #[cfg(feature = "u128")]
88        pub use super::{
89            ZETTA_BIT, ZEBI_BIT, YOTTA_BIT, YOBI_BIT,
90        };
91    }
92
93    #[rustfmt::skip]
94    pub mod bytes {
95        pub use super::{
96            BYTE,
97            KILO_BYTE, KIBI_BYTE, MEGA_BYTE, MEBI_BYTE, GIGA_BYTE, GIBI_BYTE,
98            TERA_BYTE, TEBI_BYTE, PETA_BYTE, PEBI_BYTE, EXA_BYTE, EXBI_BYTE,
99        };
100
101        #[cfg(feature = "u128")]
102        pub use super::{
103            ZETTA_BYTE, ZEBI_BYTE, YOTTA_BYTE, YOBI_BYTE,
104        };
105    }
106
107    #[rustfmt::skip]
108    pub mod prefixed {
109        pub use super::{
110            KILO_BIT, KIBI_BIT, KILO_BYTE, KIBI_BYTE, MEGA_BIT, MEBI_BIT, MEGA_BYTE, MEBI_BYTE,
111            GIGA_BIT, GIBI_BIT, GIGA_BYTE, GIBI_BYTE, TERA_BIT, TEBI_BIT, TERA_BYTE, TEBI_BYTE,
112            PETA_BIT, PEBI_BIT, PETA_BYTE, PEBI_BYTE, EXA_BIT, EXBI_BIT, EXA_BYTE, EXBI_BYTE,
113        };
114
115        #[cfg(feature = "u128")]
116        pub use super::{
117            ZETTA_BIT, ZEBI_BIT, ZETTA_BYTE, ZEBI_BYTE,
118            YOTTA_BIT, YOBI_BIT, YOTTA_BYTE, YOBI_BYTE,
119        };
120    }
121
122    #[rustfmt::skip]
123    pub mod all {
124        pub use super::{
125            BIT, BYTE,
126            KILO_BIT, KIBI_BIT, KILO_BYTE, KIBI_BYTE, MEGA_BIT, MEBI_BIT, MEGA_BYTE, MEBI_BYTE,
127            GIGA_BIT, GIBI_BIT, GIGA_BYTE, GIBI_BYTE, TERA_BIT, TEBI_BIT, TERA_BYTE, TEBI_BYTE,
128            PETA_BIT, PEBI_BIT, PETA_BYTE, PEBI_BYTE, EXA_BIT, EXBI_BIT, EXA_BYTE, EXBI_BYTE,
129        };
130
131        #[cfg(feature = "u128")]
132        pub use super::{
133            ZETTA_BIT, ZEBI_BIT, ZETTA_BYTE, ZEBI_BYTE,
134            YOTTA_BIT, YOBI_BIT, YOTTA_BYTE, YOBI_BYTE,
135        };
136    }
137
138    pub const NOPREFIX: [Unit; 2] = [BIT, BYTE];
139
140    #[rustfmt::skip]
141    pub const DECIMAL: [Unit; {
142        #[cfg(feature = "u128")] { 16 }
143        #[cfg(not(feature = "u128"))] { 12 }
144    }] = [
145        KILO_BIT, KILO_BYTE, MEGA_BIT, MEGA_BYTE, GIGA_BIT, GIGA_BYTE,
146        TERA_BIT, TERA_BYTE, PETA_BIT, PETA_BYTE, EXA_BIT, EXA_BYTE,
147        #[cfg(feature = "u128")] ZETTA_BIT,
148        #[cfg(feature = "u128")] ZETTA_BYTE,
149        #[cfg(feature = "u128")] YOTTA_BIT,
150        #[cfg(feature = "u128")] YOTTA_BYTE,
151    ];
152
153    #[rustfmt::skip]
154    pub const BINARY: [Unit; {
155        #[cfg(feature = "u128")] { 16 }
156        #[cfg(not(feature = "u128"))] { 12 }
157    }] = [
158        KIBI_BIT, KIBI_BYTE, MEBI_BIT, MEBI_BYTE, GIBI_BIT, GIBI_BYTE,
159        TEBI_BIT, TEBI_BYTE, PEBI_BIT, PEBI_BYTE, EXBI_BIT, EXBI_BYTE,
160        #[cfg(feature = "u128")] ZEBI_BIT,
161        #[cfg(feature = "u128")] ZEBI_BYTE,
162        #[cfg(feature = "u128")] YOBI_BIT,
163        #[cfg(feature = "u128")] YOBI_BYTE,
164    ];
165
166    #[rustfmt::skip]
167    pub const BITS: [Unit; {
168        #[cfg(feature = "u128")] { 17 }
169        #[cfg(not(feature = "u128"))] { 13 }
170    }] = [
171        BIT, KILO_BIT, KIBI_BIT, MEGA_BIT, MEBI_BIT, GIGA_BIT, GIBI_BIT,
172        TERA_BIT, TEBI_BIT, PETA_BIT, PEBI_BIT, EXA_BIT, EXBI_BIT,
173        #[cfg(feature = "u128")] ZETTA_BIT,
174        #[cfg(feature = "u128")] ZEBI_BIT,
175        #[cfg(feature = "u128")] YOTTA_BIT,
176        #[cfg(feature = "u128")] YOBI_BIT,
177    ];
178
179    #[rustfmt::skip]
180    pub const BYTES: [Unit; {
181        #[cfg(feature = "u128")] { 17 }
182        #[cfg(not(feature = "u128"))] { 13 }
183    }] = [
184        BYTE, KILO_BYTE, KIBI_BYTE, MEGA_BYTE, MEBI_BYTE, GIGA_BYTE, GIBI_BYTE,
185        TERA_BYTE, TEBI_BYTE, PETA_BYTE, PEBI_BYTE, EXA_BYTE, EXBI_BYTE,
186        #[cfg(feature = "u128")] ZETTA_BYTE,
187        #[cfg(feature = "u128")] ZEBI_BYTE,
188        #[cfg(feature = "u128")] YOTTA_BYTE,
189        #[cfg(feature = "u128")] YOBI_BYTE,
190    ];
191
192    #[rustfmt::skip]
193    pub const PREFIXED: [Unit; {
194        #[cfg(feature = "u128")] { 32 }
195        #[cfg(not(feature = "u128"))] { 24 }
196    }] = [
197        KILO_BIT, KIBI_BIT, KILO_BYTE, KIBI_BYTE, MEGA_BIT, MEBI_BIT, MEGA_BYTE, MEBI_BYTE,
198        GIGA_BIT, GIBI_BIT, GIGA_BYTE, GIBI_BYTE, TERA_BIT, TEBI_BIT, TERA_BYTE, TEBI_BYTE,
199        PETA_BIT, PEBI_BIT, PETA_BYTE, PEBI_BYTE, EXA_BIT, EXBI_BIT, EXA_BYTE, EXBI_BYTE,
200        #[cfg(feature = "u128")] ZETTA_BIT,
201        #[cfg(feature = "u128")] ZEBI_BIT,
202        #[cfg(feature = "u128")] ZETTA_BYTE,
203        #[cfg(feature = "u128")] ZEBI_BYTE,
204        #[cfg(feature = "u128")] YOTTA_BIT,
205        #[cfg(feature = "u128")] YOBI_BIT,
206        #[cfg(feature = "u128")] YOTTA_BYTE,
207        #[cfg(feature = "u128")] YOBI_BYTE,
208    ];
209
210    #[rustfmt::skip]
211    pub const ALL: [Unit; {
212        #[cfg(feature = "u128")] { 34 }
213        #[cfg(not(feature = "u128"))] { 26 }
214    }] = [
215        BIT, BYTE,
216        KILO_BIT, KIBI_BIT, KILO_BYTE, KIBI_BYTE, MEGA_BIT, MEBI_BIT, MEGA_BYTE, MEBI_BYTE,
217        GIGA_BIT, GIBI_BIT, GIGA_BYTE, GIBI_BYTE, TERA_BIT, TEBI_BIT, TERA_BYTE, TEBI_BYTE,
218        PETA_BIT, PEBI_BIT, PETA_BYTE, PEBI_BYTE, EXA_BIT, EXBI_BIT, EXA_BYTE, EXBI_BYTE,
219        #[cfg(feature = "u128")] ZETTA_BIT,
220        #[cfg(feature = "u128")] ZEBI_BIT,
221        #[cfg(feature = "u128")] ZETTA_BYTE,
222        #[cfg(feature = "u128")] ZEBI_BYTE,
223        #[cfg(feature = "u128")] YOTTA_BIT,
224        #[cfg(feature = "u128")] YOBI_BIT,
225        #[cfg(feature = "u128")] YOTTA_BYTE,
226        #[cfg(feature = "u128")] YOBI_BYTE,
227    ];
228}
229
230impl SizeVariant {
231    pub const fn is_bit(&self) -> bool {
232        *self as u8 == 0
233    }
234
235    pub const fn is_byte(&self) -> bool {
236        *self as u8 == 1
237    }
238
239    pub const fn mode(&self) -> Mode {
240        if let Bit = self {
241            return Mode::Bits;
242        }
243        Mode::Default
244    }
245
246    pub const fn symbol(&self) -> &'static str {
247        match self {
248            Bit => "b",
249            Byte => "B",
250        }
251    }
252
253    pub const fn symbol_long(&self, plural: bool, caps: bool) -> &'static str {
254        match self {
255            Bit => match (plural, caps) {
256                (true, true) => "Bits",
257                (false, true) => "Bit",
258                (true, false) => "bits",
259                (false, false) => "bit",
260            },
261            Byte => match (plural, caps) {
262                (true, true) => "Bytes",
263                (false, true) => "Byte",
264                (true, false) => "bytes",
265                (false, false) => "byte",
266            },
267        }
268    }
269
270    pub const fn effective_value(&self) -> u8 {
271        match self {
272            Bit => 1,
273            Byte => 8,
274        }
275    }
276}
277
278impl fmt::Display for SizeVariant {
279    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280        let variant = if f.alternate() {
281            self.symbol_long(f.sign_plus(), true)
282        } else {
283            self.symbol()
284        };
285        f.write_str(variant)
286    }
287}
288
289impl FromStr for SizeVariant {
290    type Err = ParseError;
291
292    fn from_str(s: &str) -> Result<Self, Self::Err> {
293        match s {
294            "" => Err(ParseError::EmptyInput),
295            "b" => Ok(Bit),
296            "B" => Ok(Byte),
297            s => match s.to_lowercase().as_str() {
298                "bit" | "bits" => Ok(Bit),
299                "byte" | "bytes" => Ok(Byte),
300                _ => Err(ParseError::InvalidSizeVariant),
301            },
302        }
303    }
304}
305
306impl From<(UnitPrefix, SizeVariant)> for Unit {
307    fn from((prefix, variant): (UnitPrefix, SizeVariant)) -> Self {
308        Self::of(prefix, variant)
309    }
310}
311
312impl From<SizeVariant> for Unit {
313    fn from(variant: SizeVariant) -> Self {
314        Self(None, variant)
315    }
316}
317
318impl From<UnitPrefix> for Unit {
319    fn from(prefix: UnitPrefix) -> Self {
320        Self::of(prefix, SizeVariant::Byte)
321    }
322}
323
324impl Unit {
325    pub const MIN: Unit = Unit(None, Bit);
326    pub const MAX: Unit = Unit::of(UnitPrefix::MAX, Byte);
327
328    #[inline(always)]
329    pub const fn prefix(&self) -> Option<UnitPrefix> {
330        self.0
331    }
332
333    #[inline(always)]
334    pub const fn size_variant(&self) -> SizeVariant {
335        self.1
336    }
337
338    #[inline(always)]
339    const fn of(prefix: UnitPrefix, size_variant: SizeVariant) -> Self {
340        Self(Some(prefix), size_variant)
341    }
342
343    pub const fn is_decimal(&self) -> bool {
344        if let Some(prefix) = self.0 {
345            return prefix.is_decimal();
346        }
347        false
348    }
349
350    pub const fn is_binary(&self) -> bool {
351        if let Some(prefix) = self.0 {
352            return prefix.is_binary();
353        }
354        false
355    }
356
357    pub const fn is_prefixed(&self) -> bool {
358        self.0.is_some()
359    }
360
361    pub const fn is_bit(&self) -> bool {
362        self.1.is_bit()
363    }
364
365    pub const fn is_byte(&self) -> bool {
366        self.1.is_byte()
367    }
368
369    pub const fn index(&self) -> usize {
370        if let Some(prefix) = self.0 {
371            return prefix.index() + 1;
372        }
373        0
374    }
375
376    pub const fn decimal(&self) -> Self {
377        Self(
378            match self.0 {
379                Some(prefix) => Some(prefix.decimal()),
380                None => None,
381            },
382            self.1,
383        )
384    }
385
386    pub const fn binary(&self) -> Self {
387        Self(
388            match self.0 {
389                Some(prefix) => Some(prefix.binary()),
390                None => None,
391            },
392            self.1,
393        )
394    }
395
396    pub const fn bit(&self) -> Self {
397        Self(self.0, Bit)
398    }
399
400    pub const fn byte(&self) -> Self {
401        Self(self.0, Byte)
402    }
403
404    pub const fn effective_value(&self) -> Int {
405        (match self.0 {
406            Some(prefix) => prefix.effective_value(),
407            None => 1,
408        } * self.1.effective_value() as Int)
409    }
410
411    pub const fn mode(&self) -> Mode {
412        match (self.is_decimal(), self.is_bit()) {
413            (false, false) => Mode::Default,
414            (true, false) => Mode::Decimal,
415            (false, true) => Mode::Bits,
416            (true, true) => bitflags_const_or!(Mode::{Decimal | Bits}),
417        }
418    }
419
420    pub const fn symbols(&self) -> (&'static str, &'static str) {
421        (
422            match self.0 {
423                Some(prefix) => prefix.symbol(),
424                None => "",
425            },
426            self.1.symbol(),
427        )
428    }
429
430    pub fn symbol(&self) -> String {
431        let (prefix, size_variant) = self.symbols();
432        format!("{}{}", prefix, size_variant)
433    }
434
435    pub const fn symbols_long(
436        &self,
437        plural: bool,
438        multi_caps: bool,
439    ) -> (&'static str, &'static str) {
440        (
441            match self.0 {
442                Some(prefix) => prefix.symbol_long(),
443                None => "",
444            },
445            self.1
446                .symbol_long(plural, !self.is_prefixed() || multi_caps),
447        )
448    }
449
450    pub fn symbol_long(&self, plural: bool, multi_caps: bool) -> String {
451        let (prefix, size_variant) = self.symbols_long(plural, multi_caps);
452        format!("{}{}", prefix, size_variant)
453    }
454
455    // 'b', 'B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'
456    pub const fn symbol_condensed(&self) -> &'static str {
457        match self.0 {
458            Some(prefix) => prefix.symbol_initials(),
459            None => self.1.symbol(),
460        }
461    }
462
463    pub const fn symbols_initials(&self) -> (&'static str, &'static str) {
464        (
465            match self.0 {
466                Some(prefix) => prefix.symbol_initials(),
467                None => "",
468            },
469            self.1.symbol(),
470        )
471    }
472
473    pub fn symbol_initials(&self) -> String {
474        let (prefix, size_variant) = self.symbols_initials();
475        format!("{}{}", prefix, size_variant)
476    }
477}
478
479impl Ord for Unit {
480    #[inline]
481    fn cmp(&self, other: &Self) -> Ordering {
482        self.effective_value().cmp(&other.effective_value())
483    }
484}
485
486impl PartialOrd for Unit {
487    #[inline]
488    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
489        Some(self.cmp(other))
490    }
491}
492
493impl fmt::Display for Unit {
494    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
495        let unit = if f.sign_plus() {
496            self.symbol_long(!f.alternate(), true)
497        } else if f.sign_minus() {
498            if f.alternate() {
499                self.symbol_condensed().to_string()
500            } else {
501                self.symbol_initials()
502            }
503        } else {
504            self.symbol()
505        };
506        write!(f, "{}", unit)
507    }
508}
509
510impl FromStr for Unit {
511    type Err = ParseError;
512
513    fn from_str(s: &str) -> Result<Self, Self::Err> {
514        if s.is_empty() {
515            Err(ParseError::EmptyInput)
516        } else {
517            let index = s.rfind(|c| matches!(c, 'b' | 'B')).unwrap_or(0);
518            let (prefix, size_variant) = s.split_at(index);
519            let size_variant = size_variant.parse::<SizeVariant>()?;
520            #[rustfmt::skip]
521            let prefix = (!prefix.is_empty())
522                .then(|| {
523                    let prefix = prefix.parse::<UnitPrefix>();
524                    #[cfg(feature = "case-insensitive")] { prefix }
525                    #[cfg(not(feature = "case-insensitive"))]
526                    {
527                        prefix.map_err(|err| match err {
528                            ParseError::InvalidPrefixCaseFormat => {
529                                ParseError::InvalidUnitCaseFormat
530                            }
531                            err => err,
532                        })
533                    }
534                })
535                .transpose()?;
536            Ok(Unit(prefix, size_variant))
537        }
538    }
539}
540
541#[cfg(test)]
542mod tests {
543    use super::{sizes::*, *};
544
545    #[test]
546    fn size_variant() {
547        let bit = Bit;
548        assert!(bit.is_bit());
549        assert!(!bit.is_byte());
550
551        let byte = Byte;
552        assert!(byte.is_byte());
553        assert!(!byte.is_bit());
554    }
555
556    #[test]
557    fn size_variant_cmp() {
558        assert!(Bit < Byte && Byte > Bit);
559    }
560
561    #[test]
562    fn format_display_size_variant_symbol() {
563        let map = [(Bit, "b"), (Byte, "B")];
564
565        for (unit, repr) in map.iter() {
566            assert_eq!(
567                *repr,
568                unit.symbol(),
569                "expected [{:?}] to be represented as {}",
570                unit,
571                repr
572            );
573            assert_eq!(
574                *repr,
575                format!("{}", unit),
576                "expected [{:?}] to be represented as {}",
577                unit,
578                repr
579            );
580        }
581    }
582
583    #[test]
584    fn format_display_size_variant_symbol_long() {
585        #[rustfmt::skip]
586        let map = [
587            (Bit, "Bit"), (Bit, "Bits"),
588            (Byte, "Byte"), (Byte, "Bytes")
589        ];
590
591        for (index, (unit, repr)) in map.iter().enumerate() {
592            assert_eq!(
593                *repr,
594                unit.symbol_long(index % 2 != 0, true),
595                "expected [{:?}] to be represented in long form as [{}]",
596                unit,
597                repr
598            );
599            assert_eq!(
600                repr.to_lowercase(),
601                unit.symbol_long(index % 2 != 0, false),
602                "expected [{:?}] to be represented in its long single-caps form as [{}]",
603                unit,
604                repr
605            );
606            let value = if index % 2 == 0 {
607                format!("{:#}", unit)
608            } else {
609                format!("{:+#}", unit)
610            };
611            assert_eq!(
612                *repr, value,
613                "expected [{:?}] to be represented in long form as [{}]",
614                unit, repr
615            );
616        }
617    }
618
619    #[test]
620    fn size_variant_effective_value() {
621        let map = [(Bit, 1), (Byte, 8)];
622
623        for (size_variant, value) in map.iter() {
624            assert_eq!(
625                *value,
626                size_variant.effective_value(),
627                "expected [{:?}] to have the value [{}]",
628                size_variant,
629                value
630            );
631        }
632    }
633
634    #[test]
635    fn size_variant_str_parse() {
636        assert_eq!(Ok(Bit), "b".parse::<SizeVariant>());
637        assert_eq!(Ok(Byte), "B".parse::<SizeVariant>());
638        assert_eq!(Ok(Bit), "bit".parse::<SizeVariant>());
639        assert_eq!(Ok(Bit), "bits".parse::<SizeVariant>());
640        assert_eq!(Ok(Bit), "Bit".parse::<SizeVariant>());
641        assert_eq!(Ok(Bit), "Bits".parse::<SizeVariant>());
642        assert_eq!(Ok(Byte), "byte".parse::<SizeVariant>());
643        assert_eq!(Ok(Byte), "bytes".parse::<SizeVariant>());
644        assert_eq!(Ok(Byte), "Byte".parse::<SizeVariant>());
645        assert_eq!(Ok(Byte), "Bytes".parse::<SizeVariant>());
646        assert_eq!(Err(ParseError::EmptyInput), "".parse::<SizeVariant>());
647        assert_eq!(
648            Err(ParseError::InvalidSizeVariant),
649            " b ".parse::<SizeVariant>()
650        );
651        assert_eq!(
652            Err(ParseError::InvalidSizeVariant),
653            "B ".parse::<SizeVariant>()
654        );
655        assert_eq!(
656            Err(ParseError::InvalidSizeVariant),
657            " Bytes".parse::<SizeVariant>()
658        );
659    }
660
661    #[test]
662    #[rustfmt::skip]
663    fn unit_cmp() {
664        assert!(KILO_BIT  < KIBI_BIT  && KIBI_BIT  > KILO_BIT );
665        assert!(KIBI_BIT  < KILO_BYTE && KILO_BYTE > KIBI_BIT );
666        assert!(KILO_BYTE < KIBI_BYTE && KIBI_BYTE > KILO_BYTE);
667        assert!(KIBI_BYTE < MEGA_BIT  && MEGA_BIT  > KIBI_BYTE);
668        assert!(MEGA_BIT  < MEBI_BIT  && MEBI_BIT  > MEGA_BIT );
669        assert!(MEBI_BIT  < MEGA_BYTE && MEGA_BYTE > MEBI_BIT );
670        assert!(MEGA_BYTE < MEBI_BYTE && MEBI_BYTE > MEGA_BYTE);
671        assert!(MEBI_BYTE < GIGA_BIT  && GIGA_BIT  > MEBI_BYTE);
672        assert!(GIGA_BIT  < GIBI_BIT  && GIBI_BIT  > GIGA_BIT );
673        assert!(GIBI_BIT  < GIGA_BYTE && GIGA_BYTE > GIBI_BIT );
674        assert!(GIGA_BYTE < GIBI_BYTE && GIBI_BYTE > GIGA_BYTE);
675        assert!(GIBI_BYTE < TERA_BIT  && TERA_BIT  > GIBI_BYTE);
676        assert!(TERA_BIT  < TEBI_BIT  && TEBI_BIT  > TERA_BIT );
677        assert!(TEBI_BIT  < TERA_BYTE && TERA_BYTE > TEBI_BIT );
678        assert!(TERA_BYTE < TEBI_BYTE && TEBI_BYTE > TERA_BYTE);
679        assert!(TEBI_BYTE < PETA_BIT  && PETA_BIT  > TEBI_BYTE);
680        assert!(PETA_BIT  < PEBI_BIT  && PEBI_BIT  > PETA_BIT );
681        assert!(PEBI_BIT  < PETA_BYTE && PETA_BYTE > PEBI_BIT );
682        assert!(PETA_BYTE < PEBI_BYTE && PEBI_BYTE > PETA_BYTE);
683        assert!(PEBI_BYTE < EXA_BIT   && EXA_BIT   > PEBI_BYTE);
684        assert!(EXA_BIT   < EXBI_BIT  && EXBI_BIT  > EXA_BIT  );
685        assert!(EXBI_BIT  < EXA_BYTE  && EXA_BYTE  > EXBI_BIT );
686        assert!(EXA_BYTE  < EXBI_BYTE && EXBI_BYTE > EXA_BYTE );
687
688        #[cfg(feature = "u128")] assert!(EXBI_BYTE  < ZETTA_BIT  && ZETTA_BIT  > EXBI_BYTE );
689        #[cfg(feature = "u128")] assert!(ZETTA_BIT  < ZEBI_BIT   && ZEBI_BIT   > ZETTA_BIT );
690        #[cfg(feature = "u128")] assert!(ZEBI_BIT   < ZETTA_BYTE && ZETTA_BYTE > ZEBI_BIT  );
691        #[cfg(feature = "u128")] assert!(ZETTA_BYTE < ZEBI_BYTE  && ZEBI_BYTE  > ZETTA_BYTE);
692        #[cfg(feature = "u128")] assert!(ZEBI_BYTE  < YOTTA_BIT  && YOTTA_BIT  > ZEBI_BYTE );
693        #[cfg(feature = "u128")] assert!(YOTTA_BIT  < YOBI_BIT   && YOBI_BIT   > YOTTA_BIT );
694        #[cfg(feature = "u128")] assert!(YOBI_BIT   < YOTTA_BYTE && YOTTA_BYTE > YOBI_BIT  );
695        #[cfg(feature = "u128")] assert!(YOTTA_BYTE < YOBI_BYTE  && YOBI_BYTE  > YOTTA_BYTE);
696    }
697
698    #[test]
699    fn const_sizes_sorted() {
700        fn is_sorted(prefix: &mut [Unit]) -> bool {
701            let a = prefix.windows(2).all(|lr| lr[0] < lr[1]);
702            prefix.reverse();
703            let b = prefix.windows(2).all(|lr| lr[0] > lr[1]);
704            a && b
705        }
706
707        assert!(is_sorted(&mut { sizes::NOPREFIX }));
708        assert!(is_sorted(&mut { sizes::DECIMAL }));
709        assert!(is_sorted(&mut { sizes::BINARY }));
710        assert!(is_sorted(&mut { sizes::BITS }));
711        assert!(is_sorted(&mut { sizes::BYTES }));
712        assert!(is_sorted(&mut { sizes::PREFIXED }));
713        assert!(is_sorted(&mut { sizes::ALL }));
714    }
715
716    #[test]
717    fn unit_components() {
718        let b = BIT;
719        assert_eq!((None, Bit), (b.prefix(), b.size_variant()));
720
721        let kb = KILO_BIT;
722        assert_eq!((Some(Kilo), Bit), (kb.prefix(), kb.size_variant()));
723
724        #[allow(non_snake_case)]
725        let GB = GIGA_BYTE;
726        assert_eq!((Some(Giga), Byte), (GB.prefix(), GB.size_variant()));
727    }
728
729    #[test]
730    #[rustfmt::skip]
731    fn unit_decimal() {
732        assert_eq!(KILO_BIT, Unit::of(Kilo, Bit));
733        assert_eq!(MEGA_BIT, Unit::of(Mega, Bit));
734        assert_eq!(GIGA_BIT, Unit::of(Giga, Bit));
735        assert_eq!(TERA_BIT, Unit::of(Tera, Bit));
736        assert_eq!(PETA_BIT, Unit::of(Peta, Bit));
737        assert_eq!(EXA_BIT , Unit::of(Exa , Bit));
738        #[cfg(feature = "u128")] assert_eq!(ZETTA_BIT, Unit::of(Zetta, Bit));
739        #[cfg(feature = "u128")] assert_eq!(YOTTA_BIT, Unit::of(Yotta, Bit));
740        // --
741        assert_eq!(KILO_BYTE, Unit::of(Kilo, Byte));
742        assert_eq!(MEGA_BYTE, Unit::of(Mega, Byte));
743        assert_eq!(GIGA_BYTE, Unit::of(Giga, Byte));
744        assert_eq!(TERA_BYTE, Unit::of(Tera, Byte));
745        assert_eq!(PETA_BYTE, Unit::of(Peta, Byte));
746        assert_eq!(EXA_BYTE , Unit::of(Exa , Byte));
747        #[cfg(feature = "u128")] assert_eq!(ZETTA_BYTE, Unit::of(Zetta, Byte));
748        #[cfg(feature = "u128")] assert_eq!(YOTTA_BYTE, Unit::of(Yotta, Byte));
749    }
750
751    #[test]
752    fn unit_binary() {
753        assert_eq!(KIBI_BIT, Unit::of(Kibi, Bit));
754        assert_eq!(MEBI_BIT, Unit::of(Mebi, Bit));
755        assert_eq!(GIBI_BIT, Unit::of(Gibi, Bit));
756        assert_eq!(TEBI_BIT, Unit::of(Tebi, Bit));
757        assert_eq!(PEBI_BIT, Unit::of(Pebi, Bit));
758        assert_eq!(EXBI_BIT, Unit::of(Exbi, Bit));
759        #[cfg(feature = "u128")]
760        assert_eq!(ZEBI_BIT, Unit::of(Zebi, Bit));
761        #[cfg(feature = "u128")]
762        assert_eq!(YOBI_BIT, Unit::of(Yobi, Bit));
763        // --
764        assert_eq!(KIBI_BYTE, Unit::of(Kibi, Byte));
765        assert_eq!(MEBI_BYTE, Unit::of(Mebi, Byte));
766        assert_eq!(GIBI_BYTE, Unit::of(Gibi, Byte));
767        assert_eq!(TEBI_BYTE, Unit::of(Tebi, Byte));
768        assert_eq!(PEBI_BYTE, Unit::of(Pebi, Byte));
769        assert_eq!(EXBI_BYTE, Unit::of(Exbi, Byte));
770        #[cfg(feature = "u128")]
771        assert_eq!(ZEBI_BYTE, Unit::of(Zebi, Byte));
772        #[cfg(feature = "u128")]
773        assert_eq!(YOBI_BYTE, Unit::of(Yobi, Byte));
774    }
775
776    #[test]
777    #[rustfmt::skip]
778    fn unit_from_prefix_and_variant() {
779        assert_eq!(GIGA_BIT , Unit::from((Giga, Bit)) ); // Gb
780        assert_eq!(KILO_BYTE, Unit::from((Kilo, Byte))); // KB
781        assert_eq!(PEBI_BIT , (Pebi, Bit).into()      ); // Pib
782        assert_eq!(EXBI_BYTE, Unit::of(Exbi, Byte)    ); // EiB
783    }
784
785    #[test]
786    fn unit_from_prefix_and_default() {
787        assert_eq!(KILO_BYTE, Unit::from(Kilo));
788        assert_eq!(KIBI_BYTE, Unit::from(Kibi));
789        assert_eq!(GIGA_BYTE, Giga.into());
790        assert_eq!(GIBI_BYTE, Gibi.into());
791    }
792
793    #[test]
794    fn index() {
795        #[rustfmt::skip]
796        let map  = [
797            (BIT,        0), (BYTE,        0),
798            // --
799            (KILO_BIT,   1), (KILO_BYTE,   1),
800            (MEGA_BIT,   2), (MEGA_BYTE,   2),
801            (GIGA_BIT,   3), (GIGA_BYTE,   3),
802            (TERA_BIT,   4), (TERA_BYTE,   4),
803            (PETA_BIT,   5), (PETA_BYTE,   5),
804            (EXA_BIT ,   6), (EXA_BYTE ,   6),
805            #[cfg(feature = "u128")] (ZETTA_BIT ,  7),
806            #[cfg(feature = "u128")] (ZETTA_BYTE,  7),
807            #[cfg(feature = "u128")] (YOTTA_BIT ,  8),
808            #[cfg(feature = "u128")] (YOTTA_BYTE,  8),
809            // --
810            (KIBI_BIT,   1), (KIBI_BYTE,   1),
811            (MEBI_BIT,   2), (MEBI_BYTE,   2),
812            (GIBI_BIT,   3), (GIBI_BYTE,   3),
813            (TEBI_BIT,   4), (TEBI_BYTE,   4),
814            (PEBI_BIT,   5), (PEBI_BYTE,   5),
815            (EXBI_BIT,   6), (EXBI_BYTE,   6),
816            #[cfg(feature = "u128")] (ZEBI_BIT ,   7),
817            #[cfg(feature = "u128")] (ZEBI_BYTE,   7),
818            #[cfg(feature = "u128")] (YOBI_BIT ,   8),
819            #[cfg(feature = "u128")] (YOBI_BYTE,   8),
820        ];
821
822        for (unit, index) in map.iter() {
823            assert_eq!(
824                *index,
825                unit.index(),
826                "expected [{:?}] to have the index {}",
827                unit,
828                index
829            );
830        }
831    }
832
833    #[test]
834    #[rustfmt::skip]
835    fn unit_to_decimal() {
836        assert_eq!(KILO_BIT, KIBI_BIT.decimal());
837        assert_eq!(MEGA_BIT, MEBI_BIT.decimal());
838        assert_eq!(GIGA_BIT, GIBI_BIT.decimal());
839        assert_eq!(TERA_BIT, TEBI_BIT.decimal());
840        assert_eq!(PETA_BIT, PEBI_BIT.decimal());
841        assert_eq!(EXA_BIT , EXBI_BIT.decimal());
842        #[cfg(feature = "u128")] assert_eq!(ZETTA_BIT, ZEBI_BIT.decimal());
843        #[cfg(feature = "u128")] assert_eq!(YOTTA_BIT, YOBI_BIT.decimal());
844        // --
845        assert_eq!(KILO_BYTE, KIBI_BYTE.decimal());
846        assert_eq!(MEGA_BYTE, MEBI_BYTE.decimal());
847        assert_eq!(GIGA_BYTE, GIBI_BYTE.decimal());
848        assert_eq!(TERA_BYTE, TEBI_BYTE.decimal());
849        assert_eq!(PETA_BYTE, PEBI_BYTE.decimal());
850        assert_eq!(EXA_BYTE , EXBI_BYTE.decimal());
851        #[cfg(feature = "u128")] assert_eq!(ZETTA_BYTE, ZEBI_BYTE.decimal());
852        #[cfg(feature = "u128")] assert_eq!(YOTTA_BYTE, YOBI_BYTE.decimal());
853    }
854
855    #[test]
856    #[rustfmt::skip]
857    fn unit_to_binary() {
858        assert_eq!(KIBI_BIT, KILO_BIT.binary());
859        assert_eq!(MEBI_BIT, MEGA_BIT.binary());
860        assert_eq!(GIBI_BIT, GIGA_BIT.binary());
861        assert_eq!(TEBI_BIT, TERA_BIT.binary());
862        assert_eq!(PEBI_BIT, PETA_BIT.binary());
863        assert_eq!(EXBI_BIT, EXA_BIT .binary());
864        #[cfg(feature = "u128")] assert_eq!(ZEBI_BIT, ZETTA_BIT.binary());
865        #[cfg(feature = "u128")] assert_eq!(YOBI_BIT, YOTTA_BIT.binary());
866        // --
867        assert_eq!(KIBI_BYTE, KILO_BYTE.binary());
868        assert_eq!(MEBI_BYTE, MEGA_BYTE.binary());
869        assert_eq!(GIBI_BYTE, GIGA_BYTE.binary());
870        assert_eq!(TEBI_BYTE, TERA_BYTE.binary());
871        assert_eq!(PEBI_BYTE, PETA_BYTE.binary());
872        assert_eq!(EXBI_BYTE, EXA_BYTE .binary());
873        #[cfg(feature = "u128")] assert_eq!(ZEBI_BYTE, ZETTA_BYTE.binary());
874        #[cfg(feature = "u128")] assert_eq!(YOBI_BYTE, YOTTA_BYTE.binary());
875    }
876
877    #[test]
878    #[rustfmt::skip]
879    fn unit_to_bits() {
880        assert_eq!(KILO_BIT, KILO_BIT.bit());
881        assert_eq!(MEGA_BIT, MEGA_BIT.bit());
882        assert_eq!(GIGA_BIT, GIGA_BIT.bit());
883        assert_eq!(TERA_BIT, TERA_BIT.bit());
884        assert_eq!(PETA_BIT, PETA_BIT.bit());
885        assert_eq!(EXA_BIT , EXA_BIT .bit());
886        #[cfg(feature = "u128")] assert_eq!(ZETTA_BIT, ZETTA_BIT.bit());
887        #[cfg(feature = "u128")] assert_eq!(YOTTA_BIT, YOTTA_BIT.bit());
888        // --
889        assert_eq!(KILO_BIT, KILO_BYTE.bit());
890        assert_eq!(MEGA_BIT, MEGA_BYTE.bit());
891        assert_eq!(GIGA_BIT, GIGA_BYTE.bit());
892        assert_eq!(TERA_BIT, TERA_BYTE.bit());
893        assert_eq!(PETA_BIT, PETA_BYTE.bit());
894        assert_eq!(EXA_BIT , EXA_BYTE .bit());
895        #[cfg(feature = "u128")] assert_eq!(ZETTA_BIT, ZETTA_BYTE.bit());
896        #[cfg(feature = "u128")] assert_eq!(YOTTA_BIT, YOTTA_BYTE.bit());
897    }
898
899    #[test]
900    fn unit_to_bytes() {
901        assert_eq!(KIBI_BYTE, KIBI_BIT.byte());
902        assert_eq!(MEBI_BYTE, MEBI_BIT.byte());
903        assert_eq!(GIBI_BYTE, GIBI_BIT.byte());
904        assert_eq!(TEBI_BYTE, TEBI_BIT.byte());
905        assert_eq!(PEBI_BYTE, PEBI_BIT.byte());
906        assert_eq!(EXBI_BYTE, EXBI_BIT.byte());
907        #[cfg(feature = "u128")]
908        assert_eq!(ZEBI_BYTE, ZEBI_BIT.byte());
909        #[cfg(feature = "u128")]
910        assert_eq!(YOBI_BYTE, YOBI_BIT.byte());
911        // --
912        assert_eq!(KIBI_BYTE, KIBI_BYTE.byte());
913        assert_eq!(MEBI_BYTE, MEBI_BYTE.byte());
914        assert_eq!(GIBI_BYTE, GIBI_BYTE.byte());
915        assert_eq!(TEBI_BYTE, TEBI_BYTE.byte());
916        assert_eq!(PEBI_BYTE, PEBI_BYTE.byte());
917        assert_eq!(EXBI_BYTE, EXBI_BYTE.byte());
918        #[cfg(feature = "u128")]
919        assert_eq!(ZEBI_BYTE, ZEBI_BYTE.byte());
920        #[cfg(feature = "u128")]
921        assert_eq!(YOBI_BYTE, YOBI_BYTE.byte());
922    }
923
924    #[test]
925    fn unit_is_decimal() {
926        assert!(!BIT.is_decimal());
927        assert!(!BYTE.is_decimal());
928        for unit in sizes::DECIMAL.iter() {
929            assert!(unit.is_decimal())
930        }
931        for unit in sizes::BINARY.iter() {
932            assert!(!unit.is_decimal())
933        }
934    }
935
936    #[test]
937    fn unit_is_binary() {
938        assert!(!BIT.is_binary());
939        assert!(!BYTE.is_binary());
940        for unit in sizes::BINARY.iter() {
941            assert!(unit.is_binary())
942        }
943        for unit in sizes::DECIMAL.iter() {
944            assert!(!unit.is_binary())
945        }
946    }
947
948    #[test]
949    fn unit_is_bit() {
950        for unit in sizes::BITS.iter() {
951            assert!(unit.is_bit())
952        }
953        for unit in sizes::BYTES.iter() {
954            assert!(!unit.is_bit())
955        }
956    }
957
958    #[test]
959    fn unit_is_byte() {
960        for unit in sizes::BYTES.iter() {
961            assert!(unit.is_byte())
962        }
963        for unit in sizes::BITS.iter() {
964            assert!(!unit.is_byte())
965        }
966    }
967
968    #[test]
969    fn unit_is_prefixed() {
970        for unit in sizes::NOPREFIX.iter() {
971            assert!(!unit.is_prefixed())
972        }
973        for unit in sizes::PREFIXED.iter() {
974            assert!(unit.is_prefixed())
975        }
976    }
977
978    #[test]
979    #[rustfmt::skip]
980    fn unit_from_variant() {
981        assert_eq!(BIT , Unit::from(Bit)); // b
982        assert_eq!(BYTE, Byte.into()    ); // B
983    }
984
985    #[test]
986    fn unit_effective_value() {
987        #[rustfmt::skip]
988        let map = [
989            (BIT     , 1),                          (BYTE     , 8),
990            (KILO_BIT, 1000),                       (KILO_BYTE, 8000),
991            (MEGA_BIT, 1000000),                    (MEGA_BYTE, 8000000),
992            (GIGA_BIT, 1000000000),                 (GIGA_BYTE, 8000000000),
993            (TERA_BIT, 1000000000000),              (TERA_BYTE, 8000000000000),
994            (PETA_BIT, 1000000000000000),           (PETA_BYTE, 8000000000000000),
995            (EXA_BIT , 1000000000000000000),        (EXA_BYTE , 8000000000000000000),
996            #[cfg(feature = "u128")] (ZETTA_BIT , 1000000000000000000000),
997            #[cfg(feature = "u128")] (YOTTA_BIT , 1000000000000000000000000),
998            #[cfg(feature = "u128")] (ZETTA_BYTE, 8000000000000000000000),
999            #[cfg(feature = "u128")] (YOTTA_BYTE, 8000000000000000000000000),
1000            (KIBI_BIT, 1024),                       (KIBI_BYTE, 8192),
1001            (MEBI_BIT, 1048576),                    (MEBI_BYTE, 8388608),
1002            (GIBI_BIT, 1073741824),                 (GIBI_BYTE, 8589934592),
1003            (TEBI_BIT, 1099511627776),              (TEBI_BYTE, 8796093022208),
1004            (PEBI_BIT, 1125899906842624),           (PEBI_BYTE, 9007199254740992),
1005            (EXBI_BIT, 1152921504606846976),        (EXBI_BYTE, 9223372036854775808),
1006            #[cfg(feature = "u128")] (ZEBI_BIT , 1180591620717411303424),
1007            #[cfg(feature = "u128")] (YOBI_BIT , 1208925819614629174706176),
1008            #[cfg(feature = "u128")] (ZEBI_BYTE, 9444732965739290427392),
1009            #[cfg(feature = "u128")] (YOBI_BYTE, 9671406556917033397649408),
1010        ];
1011
1012        for (unit, value) in map.iter() {
1013            assert_eq!(
1014                *value,
1015                unit.effective_value(),
1016                "expected [{:?}] to have the value [{}]",
1017                unit,
1018                value
1019            );
1020        }
1021    }
1022
1023    #[test]
1024    fn unit_min_max() {
1025        assert_eq!(Unit(None, Bit), Unit::MIN);
1026        #[cfg(feature = "u128")]
1027        assert_eq!(Unit(Some(Yobi), Byte), Unit::MAX);
1028        #[cfg(not(feature = "u128"))]
1029        assert_eq!(Unit(Some(Exbi), Byte), Unit::MAX);
1030    }
1031
1032    #[test]
1033    fn unit_format_and_display_symbol() {
1034        #[rustfmt::skip]
1035        let map = [
1036        //  size,
1037        //   |         condensed,
1038        //   |           |  initials,
1039        //   |           |    |   normal,
1040        //   |           |    |     |    long,
1041        //   |           |    |     |      |          long_single_caps,
1042        //   |           |    |     |      |            |          long_extra,
1043        //   |           |    |     |      |            |            |          long_extra_single_caps,
1044        //   |           |    |     |      |            |            |            |
1045            (BIT      , "b", "b" , "b"  , "Bit"      , "Bit"      , "Bits"     , "Bits"     ),
1046            (BYTE     , "B", "B" , "B"  , "Byte"     , "Byte"     , "Bytes"    , "Bytes"    ),
1047            (KILO_BIT , "K", "Kb", "Kb" , "KiloBit"  , "Kilobit"  , "KiloBits" , "Kilobits" ),
1048            (KILO_BYTE, "K", "KB", "KB" , "KiloByte" , "Kilobyte" , "KiloBytes", "Kilobytes"),
1049            (MEGA_BIT , "M", "Mb", "Mb" , "MegaBit"  , "Megabit"  , "MegaBits" , "Megabits" ),
1050            (MEGA_BYTE, "M", "MB", "MB" , "MegaByte" , "Megabyte" , "MegaBytes", "Megabytes"),
1051            (GIGA_BIT , "G", "Gb", "Gb" , "GigaBit"  , "Gigabit"  , "GigaBits" , "Gigabits" ),
1052            (GIGA_BYTE, "G", "GB", "GB" , "GigaByte" , "Gigabyte" , "GigaBytes", "Gigabytes"),
1053            (TERA_BIT , "T", "Tb", "Tb" , "TeraBit"  , "Terabit"  , "TeraBits" , "Terabits" ),
1054            (TERA_BYTE, "T", "TB", "TB" , "TeraByte" , "Terabyte" , "TeraBytes", "Terabytes"),
1055            (PETA_BIT , "P", "Pb", "Pb" , "PetaBit"  , "Petabit"  , "PetaBits" , "Petabits" ),
1056            (PETA_BYTE, "P", "PB", "PB" , "PetaByte" , "Petabyte" , "PetaBytes", "Petabytes"),
1057            (EXA_BIT  , "E", "Eb", "Eb" , "ExaBit"   , "Exabit"   , "ExaBits"  , "Exabits"  ),
1058            (EXA_BYTE , "E", "EB", "EB" , "ExaByte"  , "Exabyte"  , "ExaBytes" , "Exabytes" ),
1059            #[cfg(feature = "u128")] (ZETTA_BIT , "Z", "Zb", "Zb" , "ZettaBit" , "Zettabit" , "ZettaBits" , "Zettabits" ),
1060            #[cfg(feature = "u128")] (ZETTA_BYTE, "Z", "ZB", "ZB" , "ZettaByte", "Zettabyte", "ZettaBytes", "Zettabytes"),
1061            #[cfg(feature = "u128")] (YOTTA_BIT , "Y", "Yb", "Yb" , "YottaBit" , "Yottabit" , "YottaBits" , "Yottabits" ),
1062            #[cfg(feature = "u128")] (YOTTA_BYTE, "Y", "YB", "YB" , "YottaByte", "Yottabyte", "YottaBytes", "Yottabytes"),
1063            (KIBI_BIT , "K", "Kb", "Kib", "KibiBit"  , "Kibibit"  , "KibiBits" , "Kibibits" ),
1064            (KIBI_BYTE, "K", "KB", "KiB", "KibiByte" , "Kibibyte" , "KibiBytes", "Kibibytes"),
1065            (MEBI_BIT , "M", "Mb", "Mib", "MebiBit"  , "Mebibit"  , "MebiBits" , "Mebibits" ),
1066            (MEBI_BYTE, "M", "MB", "MiB", "MebiByte" , "Mebibyte" , "MebiBytes", "Mebibytes"),
1067            (GIBI_BIT , "G", "Gb", "Gib", "GibiBit"  , "Gibibit"  , "GibiBits" , "Gibibits" ),
1068            (GIBI_BYTE, "G", "GB", "GiB", "GibiByte" , "Gibibyte" , "GibiBytes", "Gibibytes"),
1069            (TEBI_BIT , "T", "Tb", "Tib", "TebiBit"  , "Tebibit"  , "TebiBits" , "Tebibits" ),
1070            (TEBI_BYTE, "T", "TB", "TiB", "TebiByte" , "Tebibyte" , "TebiBytes", "Tebibytes"),
1071            (PEBI_BIT , "P", "Pb", "Pib", "PebiBit"  , "Pebibit"  , "PebiBits" , "Pebibits" ),
1072            (PEBI_BYTE, "P", "PB", "PiB", "PebiByte" , "Pebibyte" , "PebiBytes", "Pebibytes"),
1073            (EXBI_BIT , "E", "Eb", "Eib", "ExbiBit"  , "Exbibit"  , "ExbiBits" , "Exbibits" ),
1074            (EXBI_BYTE, "E", "EB", "EiB", "ExbiByte" , "Exbibyte" , "ExbiBytes", "Exbibytes"),
1075            #[cfg(feature = "u128")] (ZEBI_BIT , "Z", "Zb", "Zib", "ZebiBit"  , "Zebibit"  , "ZebiBits"  , "Zebibits"  ),
1076            #[cfg(feature = "u128")] (ZEBI_BYTE, "Z", "ZB", "ZiB", "ZebiByte" , "Zebibyte" , "ZebiBytes" , "Zebibytes" ),
1077            #[cfg(feature = "u128")] (YOBI_BIT , "Y", "Yb", "Yib", "YobiBit"  , "Yobibit"  , "YobiBits"  , "Yobibits"  ),
1078            #[cfg(feature = "u128")] (YOBI_BYTE, "Y", "YB", "YiB", "YobiByte" , "Yobibyte" , "YobiBytes" , "Yobibytes" ),
1079        ];
1080
1081        for (
1082            unit,
1083            condensed,
1084            initials,
1085            normal,
1086            long,
1087            long_single_caps,
1088            long_extra,
1089            long_extra_single_caps,
1090        ) in map.iter()
1091        {
1092            assert_eq!(
1093                (*condensed, *condensed),
1094                (unit.symbol_condensed(), format!("{:-#}", unit).as_str()),
1095                "expected [{:?}] to be condensed as [{}]",
1096                unit,
1097                condensed
1098            );
1099            assert_eq!(
1100                (initials.to_string(), initials.to_string()),
1101                (unit.symbol_initials(), format!("{:-}", unit)),
1102                "expected [{:?}] to have initials [{}]",
1103                unit,
1104                initials
1105            );
1106            assert_eq!(
1107                (normal.to_string(), normal.to_string()),
1108                (unit.symbol(), format!("{}", unit)),
1109                "expected [{:?}] to be represented as [{}]",
1110                unit,
1111                normal
1112            );
1113            assert_eq!(
1114                (long.to_string(), long.to_string()),
1115                (unit.symbol_long(false, true), format!("{:+#}", unit)),
1116                "expected [{:?}] to be represented in long form as [{}]",
1117                unit,
1118                long
1119            );
1120            assert_eq!(
1121                long_single_caps.to_string(),
1122                unit.symbol_long(false, false),
1123                "expected [{:?}] to be represented in long single-caps form as [{}]",
1124                unit,
1125                long
1126            );
1127            assert_eq!(
1128                (long_extra.to_string(), long_extra.to_string()),
1129                (unit.symbol_long(true, true), format!("{:+}", unit)),
1130                "expected [{:?}] to be represented in long, plural form as [{}]",
1131                unit,
1132                long_extra
1133            );
1134            assert_eq!(
1135                long_extra_single_caps.to_string(),
1136                unit.symbol_long(true, false),
1137                "expected [{:?}] to be represented in long, plural, single-caps form as [{}]",
1138                unit,
1139                long_extra
1140            );
1141        }
1142    }
1143
1144    #[test]
1145    fn unit_str_parse() {
1146        assert_eq!(Ok(BIT), "b".parse::<Unit>());
1147        assert_eq!(Ok(BYTE), "B".parse::<Unit>());
1148        assert_eq!(Ok(KILO_BIT), "kb".parse::<Unit>());
1149        assert_eq!(Ok(KILO_BYTE), "kB".parse::<Unit>()); // small caps 'k' is only valid as decimal
1150        assert_eq!(Ok(KILO_BYTE), "KB".parse::<Unit>());
1151        assert_eq!(Ok(KIBI_BIT), "Kib".parse::<Unit>());
1152        assert_eq!(Ok(KIBI_BYTE), "KiB".parse::<Unit>());
1153        #[rustfmt::skip]
1154        assert_eq!(
1155            {
1156                #[cfg(not(feature = "case-insensitive"))]
1157                { Err(ParseError::InvalidUnitCaseFormat) }
1158                #[cfg(feature = "case-insensitive")]
1159                { Ok(KIBI_BIT) }
1160            },
1161            "kib".parse::<Unit>()
1162        );
1163        #[rustfmt::skip]
1164        assert_eq!(
1165            {
1166                #[cfg(not(feature = "case-insensitive"))]
1167                { Err(ParseError::InvalidUnitCaseFormat) }
1168                #[cfg(feature = "case-insensitive")]
1169                { Ok(MEGA_BIT) }
1170            },
1171            // with the default case sensitivity on,
1172            // the only valid small-caps prefix is `k`
1173            // even then, it's only valid in the decimal system
1174            // so while 'kB' is valid, 'kib' is not
1175            // turn on the `feature="case-insensitive"` flag to relax this
1176            // and allow all prefixes to be parsed case-insensitively
1177            // 'kb', 'mB', 'gIB' alike
1178            "mb".parse::<Unit>()
1179        );
1180        assert_eq!(Ok(MEGA_BIT), "Mb".parse::<Unit>());
1181        assert_eq!(Ok(MEGA_BYTE), "MB".parse::<Unit>());
1182        assert_eq!(Ok(MEBI_BIT), "Mib".parse::<Unit>());
1183        assert_eq!(Ok(MEBI_BYTE), "MiB".parse::<Unit>());
1184        #[rustfmt::skip]
1185        assert_eq!(
1186            {
1187                #[cfg(not(feature = "case-insensitive"))]
1188                { Err(ParseError::InvalidUnitCaseFormat) }
1189                #[cfg(feature = "case-insensitive")]
1190                { Ok(MEBI_BIT) }
1191            },
1192            "mib".parse::<Unit>()
1193        );
1194        assert_eq!(Ok(MEGA_BIT), "MegaBit".parse::<Unit>());
1195        assert_eq!(Ok(MEGA_BYTE), "MegaByte".parse::<Unit>());
1196        assert_eq!(Ok(GIGA_BIT), "gigabit".parse::<Unit>()); // it is case insensitive in the long form
1197        assert_eq!(Ok(GIGA_BYTE), "gigabyte".parse::<Unit>());
1198        assert_eq!(Err(ParseError::EmptyInput), "".parse::<Unit>());
1199        assert_eq!(Err(ParseError::InvalidSizeVariant), "m".parse::<Unit>());
1200        assert_eq!(Err(ParseError::InvalidPrefix), "m b".parse::<Unit>());
1201    }
1202}