xbytes/
prefix.rs

1use super::{Int, ParseError};
2use std::{fmt, str::FromStr};
3
4#[rustfmt::skip]
5#[derive(Eq, Ord, Copy, Clone, Debug, PartialEq, PartialOrd)]
6pub enum UnitPrefix {
7    Kilo, Kibi,
8    Mega, Mebi,
9    Giga, Gibi,
10    Tera, Tebi,
11    Peta, Pebi,
12    Exa , Exbi,
13    #[cfg(feature = "u128")] Zetta,
14    #[cfg(feature = "u128")] Zebi ,
15    #[cfg(feature = "u128")] Yotta,
16    #[cfg(feature = "u128")] Yobi ,
17}
18
19use UnitPrefix::*;
20
21impl UnitPrefix {
22    #[rustfmt::skip]
23    pub const DECIMAL: [UnitPrefix; {
24        #[cfg(feature = "u128")] { 8 }
25        #[cfg(not(feature = "u128"))] { 6 }
26    }] = [
27        Kilo, Mega, Giga, Tera, Peta, Exa,
28        #[cfg(feature = "u128")] Zetta,
29        #[cfg(feature = "u128")] Yotta,
30    ];
31
32    #[rustfmt::skip]
33    pub const BINARY: [UnitPrefix; {
34        #[cfg(feature = "u128")] { 8 }
35        #[cfg(not(feature = "u128"))] { 6 }
36    }] = [
37        Kibi, Mebi, Gibi, Tebi, Pebi, Exbi,
38        #[cfg(feature = "u128")] Zebi,
39        #[cfg(feature = "u128")] Yobi,
40    ];
41
42    #[rustfmt::skip]
43    pub const ALL: [UnitPrefix; {
44        #[cfg(feature = "u128")] { 16 }
45        #[cfg(not(feature = "u128"))] { 12 }
46    }] = [
47        Kilo, Kibi, Mega, Mebi, Giga, Gibi,
48        Tera, Tebi, Peta, Pebi, Exa, Exbi,
49        #[cfg(feature = "u128")] Zetta,
50        #[cfg(feature = "u128")] Zebi,
51        #[cfg(feature = "u128")] Yotta,
52        #[cfg(feature = "u128")] Yobi,
53    ];
54
55    pub const MIN: UnitPrefix = Kilo;
56
57    #[rustfmt::skip]
58    pub const MAX: UnitPrefix = {
59        #[cfg(feature = "u128")]      { Yobi }
60        #[cfg(not(feature = "u128"))] { Exbi }
61    };
62
63    pub const fn is_decimal(&self) -> bool {
64        ((*self as u8) & 1) == 0
65    }
66
67    pub const fn is_binary(&self) -> bool {
68        ((*self as u8) & 1) == 1
69    }
70
71    pub const fn index(&self) -> usize {
72        (*self as usize) / 2
73    }
74
75    pub const fn decimal(&self) -> Self {
76        if self.is_binary() {
77            return Self::DECIMAL[self.index()];
78        }
79        *self
80    }
81
82    pub const fn binary(&self) -> Self {
83        if self.is_decimal() {
84            return Self::BINARY[self.index()];
85        }
86        *self
87    }
88
89    #[rustfmt::skip]
90    #[inline(always)]
91    pub const fn effective_value(&self) -> Int {
92        match self {
93            Kibi => 1 << 10,   Kilo => 1000,
94            Mebi => 1 << 20,   Mega => 1000000,
95            Gibi => 1 << 30,   Giga => 1000000000,
96            Tebi => 1 << 40,   Tera => 1000000000000,
97            Pebi => 1 << 50,   Peta => 1000000000000000,
98            Exbi => 1 << 60,   Exa  => 1000000000000000000,
99            #[cfg(feature = "u128")] Zebi  => 1 << 70,
100            #[cfg(feature = "u128")] Yobi  => 1 << 80,
101            #[cfg(feature = "u128")] Zetta => 1000000000000000000000,
102            #[cfg(feature = "u128")] Yotta => 1000000000000000000000000,
103        }
104    }
105
106    #[rustfmt::skip]
107    pub const fn symbol(&self) -> &'static str {
108        match self {
109            Kilo => "K",   Kibi => "Ki",
110            Mega => "M",   Mebi => "Mi",
111            Giga => "G",   Gibi => "Gi",
112            Tera => "T",   Tebi => "Ti",
113            Peta => "P",   Pebi => "Pi",
114            Exa  => "E",   Exbi => "Ei",
115            #[cfg(feature = "u128")] Zetta => "Z" ,
116            #[cfg(feature = "u128")] Yotta => "Y" ,
117            #[cfg(feature = "u128")] Zebi  => "Zi",
118            #[cfg(feature = "u128")] Yobi  => "Yi",
119        }
120    }
121
122    #[rustfmt::skip]
123    pub const fn symbol_long(&self) -> &'static str {
124        match self {
125            Kilo => "Kilo",   Kibi => "Kibi",
126            Mega => "Mega",   Mebi => "Mebi",
127            Giga => "Giga",   Gibi => "Gibi",
128            Tera => "Tera",   Tebi => "Tebi",
129            Peta => "Peta",   Pebi => "Pebi",
130            Exa  => "Exa" ,   Exbi => "Exbi",
131            #[cfg(feature = "u128")] Zetta => "Zetta",
132            #[cfg(feature = "u128")] Yotta => "Yotta",
133            #[cfg(feature = "u128")] Zebi  => "Zebi" ,
134            #[cfg(feature = "u128")] Yobi  => "Yobi" ,
135        }
136    }
137
138    #[rustfmt::skip]
139    pub const fn symbol_initials(&self) -> &'static str {
140        match self {
141            Kilo | Kibi => "K",
142            Mega | Mebi => "M",
143            Giga | Gibi => "G",
144            Tera | Tebi => "T",
145            Peta | Pebi => "P",
146            Exa  | Exbi => "E",
147            #[cfg(feature = "u128")] Zetta | Zebi => "Z",
148            #[cfg(feature = "u128")] Yotta | Yobi => "Y",
149        }
150    }
151}
152
153impl fmt::Display for UnitPrefix {
154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155        let unit = if f.sign_minus() {
156            self.symbol_initials()
157        } else if f.sign_plus() {
158            self.symbol_long()
159        } else {
160            self.symbol()
161        };
162        f.write_str(unit)
163    }
164}
165
166impl FromStr for UnitPrefix {
167    type Err = ParseError;
168
169    fn from_str(s: &str) -> Result<Self, Self::Err> {
170        #[rustfmt::skip]
171        let unit = match &{
172            #[cfg(not(feature = "case-insensitive"))] { s }
173            #[cfg(feature = "case-insensitive")] {
174                if !s.is_empty() {
175                    let (first, rest) = s.split_at(1);
176                    format!("{}{}", first.to_uppercase(), rest.to_lowercase())
177                } else {
178                    s.to_string()
179                }
180            }
181        }[..] {
182            "" => return Err(ParseError::EmptyInput),
183            // https://web.archive.org/web/20150324153922/https://pacoup.com/2009/05/26/kb-kb-kib-whats-up-with-that/
184            "k" | "K"  => Kilo,   "Ki"  => Kibi,
185            "M"        => Mega,   "Mi"  => Mebi,
186            "G"        => Giga,   "Gi"  => Gibi,
187            "T"        => Tera,   "Ti"  => Tebi,
188            "P"        => Peta,   "Pi"  => Pebi,
189            "E"        => Exa ,   "Ei"  => Exbi,
190            #[cfg(feature = "u128")] "Z"   => Zetta,
191            #[cfg(feature = "u128")] "Y"   => Yotta,
192            #[cfg(feature = "u128")] "Zi"  => Zebi ,
193            #[cfg(feature = "u128")] "Yi"  => Yobi ,
194            #[cfg(not(feature = "case-insensitive"))]
195            s if (
196                matches!(s,
197                    "m" | "g" | "t" | "p" | "e" | "ki" | "mi" | "gi" | "ti" | "pi" | "ei"
198                ) || (cfg!(feature = "u128") && matches!(s, "z" | "y" | "zi" | "yi"))
199            ) => return Err(ParseError::InvalidPrefixCaseFormat),
200            s => match s.to_lowercase().as_str() {
201                "kilo" => Kilo,   "kibi" => Kibi,
202                "mega" => Mega,   "mebi" => Mebi,
203                "giga" => Giga,   "gibi" => Gibi,
204                "tera" => Tera,   "tebi" => Tebi,
205                "peta" => Peta,   "pebi" => Pebi,
206                "exa"  => Exa ,   "exbi" => Exbi,
207                #[cfg(feature = "u128")] "zetta" => Zetta,
208                #[cfg(feature = "u128")] "yotta" => Yotta,
209                #[cfg(feature = "u128")] "zebi"  => Zebi ,
210                #[cfg(feature = "u128")] "yobi"  => Yobi ,
211                _ => return Err(ParseError::InvalidPrefix),
212            }
213        };
214        Ok(unit)
215    }
216}
217
218#[cfg(test)]
219mod tests {
220    use super::*;
221
222    #[test]
223    fn decimal() {
224        #[rustfmt::skip]
225        let lhs = [
226            Kilo, Mega, Giga, Tera, Peta, Exa,
227            #[cfg(feature = "u128")] Zetta,
228            #[cfg(feature = "u128")] Yotta
229        ];
230
231        for (index, unit) in lhs.iter().enumerate() {
232            assert_eq!(unit, &UnitPrefix::DECIMAL[index]);
233            assert_ne!(unit, &UnitPrefix::BINARY[index]);
234        }
235    }
236
237    #[test]
238    fn binary() {
239        #[rustfmt::skip]
240        let lhs = [
241            Kibi, Mebi, Gibi, Tebi, Pebi, Exbi,
242            #[cfg(feature = "u128")] Zebi,
243            #[cfg(feature = "u128")] Yobi
244        ];
245
246        for (index, unit) in lhs.iter().enumerate() {
247            assert_eq!(unit, &UnitPrefix::BINARY[index]);
248            assert_ne!(unit, &UnitPrefix::DECIMAL[index]);
249        }
250    }
251
252    #[test]
253    #[rustfmt::skip]
254    fn cmp() {
255        assert!(Kilo < Kibi && Kibi > Kilo);
256        assert!(Kibi < Mega && Mega > Kibi);
257        assert!(Mega < Mebi && Mebi > Mega);
258        assert!(Mebi < Giga && Giga > Mebi);
259        assert!(Giga < Gibi && Gibi > Giga);
260        assert!(Gibi < Tera && Tera > Gibi);
261        assert!(Tera < Tebi && Tebi > Tera);
262        assert!(Tebi < Peta && Peta > Tebi);
263        assert!(Peta < Pebi && Pebi > Peta);
264        assert!(Pebi < Exa  && Exa  > Pebi);
265        assert!(Exa  < Exbi && Exbi > Exa );
266
267        #[cfg(feature = "u128")] assert!(Exbi  < Zetta && Zetta > Exbi );
268        #[cfg(feature = "u128")] assert!(Zetta < Zebi  && Zebi  > Zetta);
269        #[cfg(feature = "u128")] assert!(Zebi  < Yotta && Yotta > Zebi );
270        #[cfg(feature = "u128")] assert!(Yotta < Yobi  && Yobi  > Yotta);
271    }
272
273    #[test]
274    fn const_prefix_sorted() {
275        fn is_sorted(prefix: &mut [UnitPrefix]) -> bool {
276            let a = prefix.windows(2).all(|lr| lr[0] < lr[1]);
277            prefix.reverse();
278            let b = prefix.windows(2).all(|lr| lr[0] > lr[1]);
279            a && b
280        }
281
282        assert!(is_sorted(&mut { UnitPrefix::DECIMAL }));
283        assert!(is_sorted(&mut { UnitPrefix::BINARY }));
284        assert!(is_sorted(&mut { UnitPrefix::ALL }));
285    }
286
287    #[test]
288    fn is_decimal() {
289        for unit in UnitPrefix::DECIMAL.iter() {
290            assert!(unit.is_decimal())
291        }
292        for unit in UnitPrefix::BINARY.iter() {
293            assert!(!unit.is_decimal())
294        }
295    }
296
297    #[test]
298    fn is_binary() {
299        for unit in UnitPrefix::BINARY.iter() {
300            assert!(unit.is_binary())
301        }
302        for unit in UnitPrefix::DECIMAL.iter() {
303            assert!(!unit.is_binary())
304        }
305    }
306
307    #[test]
308    fn index() {
309        #[rustfmt::skip]
310        let map  = [
311            (Kilo,   0), (Kibi,   0),
312            (Mega,   1), (Mebi,   1),
313            (Giga,   2), (Gibi,   2),
314            (Tera,   3), (Tebi,   3),
315            (Peta,   4), (Pebi,   4),
316            (Exa ,   5), (Exbi,   5),
317            #[cfg(feature = "u128")] (Zetta,   6),
318            #[cfg(feature = "u128")] (Yotta,   7),
319            #[cfg(feature = "u128")] (Zebi ,   6),
320            #[cfg(feature = "u128")] (Yobi ,   7),
321        ];
322
323        for (unit, index) in map.iter() {
324            assert_eq!(
325                *index,
326                unit.index(),
327                "expected [{:?}] to have the index {}",
328                unit,
329                index
330            );
331        }
332    }
333
334    #[test]
335    fn to_decimal() {
336        #[rustfmt::skip]
337        let map = [
338            (Kilo,   Kilo), (Kibi,   Kilo),
339            (Mega,   Mega), (Mebi,   Mega),
340            (Giga,   Giga), (Gibi,   Giga),
341            (Tera,   Tera), (Tebi,   Tera),
342            (Peta,   Peta), (Pebi,   Peta),
343            (Exa ,   Exa ), (Exbi,   Exa ),
344            #[cfg(feature = "u128")] (Zetta,   Zetta),
345            #[cfg(feature = "u128")] (Yotta,   Yotta),
346            #[cfg(feature = "u128")] (Zebi ,   Zetta),
347            #[cfg(feature = "u128")] (Yobi ,   Yotta),
348        ];
349
350        for (unit, expected) in map.iter() {
351            assert_eq!(
352                *expected,
353                unit.decimal(),
354                "expected [{:?}] to be represented as [{:?}] in decimal",
355                unit,
356                expected
357            );
358        }
359    }
360
361    #[test]
362    fn to_binary() {
363        #[rustfmt::skip]
364        let map = [
365            (Kilo,   Kibi), (Kibi,   Kibi),
366            (Mega,   Mebi), (Mebi,   Mebi),
367            (Giga,   Gibi), (Gibi,   Gibi),
368            (Tera,   Tebi), (Tebi,   Tebi),
369            (Peta,   Pebi), (Pebi,   Pebi),
370            (Exa ,   Exbi), (Exbi,   Exbi),
371            #[cfg(feature = "u128")] (Zetta,   Zebi),
372            #[cfg(feature = "u128")] (Yotta,   Yobi),
373            #[cfg(feature = "u128")] (Zebi ,   Zebi),
374            #[cfg(feature = "u128")] (Yobi ,   Yobi),
375        ];
376
377        for (unit, expected) in map.iter() {
378            assert_eq!(
379                *expected,
380                unit.binary(),
381                "expected [{:?}] to be represented as [{:?}] in binary",
382                unit,
383                expected
384            );
385        }
386    }
387
388    #[test]
389    fn format_and_display_symbol() {
390        #[rustfmt::skip]
391        let map = [
392            (Kilo,   "K"), (Kibi,   "Ki"),
393            (Mega,   "M"), (Mebi,   "Mi"),
394            (Giga,   "G"), (Gibi,   "Gi"),
395            (Tera,   "T"), (Tebi,   "Ti"),
396            (Peta,   "P"), (Pebi,   "Pi"),
397            (Exa ,   "E"), (Exbi,   "Ei"),
398            #[cfg(feature = "u128")] (Zetta,   "Z" ),
399            #[cfg(feature = "u128")] (Yotta,   "Y" ),
400            #[cfg(feature = "u128")] (Zebi ,   "Zi"),
401            #[cfg(feature = "u128")] (Yobi ,   "Yi"),
402        ];
403
404        for (unit, repr) in map.iter() {
405            assert_eq!(
406                *repr,
407                unit.symbol(),
408                "expected [{:?}] to be represented as {}",
409                unit,
410                repr
411            );
412            assert_eq!(
413                *repr,
414                format!("{}", unit),
415                "expected [{:?}] to be represented as {}",
416                unit,
417                repr
418            );
419        }
420    }
421
422    #[test]
423    fn format_and_display_symbol_long() {
424        #[rustfmt::skip]
425        let map = [
426            (Kilo,   "Kilo"),  (Kibi,   "Kibi"),
427            (Mega,   "Mega"),  (Mebi,   "Mebi"),
428            (Giga,   "Giga"),  (Gibi,   "Gibi"),
429            (Tera,   "Tera"),  (Tebi,   "Tebi"),
430            (Peta,   "Peta"),  (Pebi,   "Pebi"),
431            (Exa ,   "Exa" ),  (Exbi,   "Exbi"),
432            #[cfg(feature = "u128")] (Zetta,   "Zetta"),
433            #[cfg(feature = "u128")] (Yotta,   "Yotta"),
434            #[cfg(feature = "u128")] (Zebi ,   "Zebi" ),
435            #[cfg(feature = "u128")] (Yobi ,   "Yobi" ),
436        ];
437
438        for (unit, repr) in map.iter() {
439            assert_eq!(
440                *repr,
441                unit.symbol_long(),
442                "expected [{:?}] to be represented in long form as {}",
443                unit,
444                repr
445            );
446            assert_eq!(
447                *repr,
448                format!("{:+}", unit),
449                "expected [{:?}] to be represented in long form as {}",
450                unit,
451                repr
452            );
453        }
454    }
455
456    #[test]
457    fn format_and_display_symbol_initials() {
458        #[rustfmt::skip]
459        let map = [
460            (Kilo,   "K"),  (Kibi,   "K"),
461            (Mega,   "M"),  (Mebi,   "M"),
462            (Giga,   "G"),  (Gibi,   "G"),
463            (Tera,   "T"),  (Tebi,   "T"),
464            (Peta,   "P"),  (Pebi,   "P"),
465            (Exa ,   "E"),  (Exbi,   "E"),
466            #[cfg(feature = "u128")] (Zetta,   "Z"),
467            #[cfg(feature = "u128")] (Yotta,   "Y"),
468            #[cfg(feature = "u128")] (Zebi ,   "Z"),
469            #[cfg(feature = "u128")] (Yobi ,   "Y"),
470        ];
471
472        for (unit, repr) in map.iter() {
473            assert_eq!(
474                *repr,
475                unit.symbol_initials(),
476                "expected [{:?}] to be represented in short form as {}",
477                unit,
478                repr
479            );
480            assert_eq!(
481                *repr,
482                format!("{:-}", unit),
483                "expected [{:?}] to be represented in short form as {}",
484                unit,
485                repr
486            );
487        }
488    }
489
490    #[test]
491    fn str_parse() {
492        #[rustfmt::skip]
493        let map = [
494            ("k"  , Ok(Kilo)),
495            ("K"  , Ok(Kilo)),  ("Ki"  , Ok(Kibi)),
496            ("M"  , Ok(Mega)),  ("Mi"  , Ok(Mebi)),
497            ("G"  , Ok(Giga)),  ("Gi"  , Ok(Gibi)),
498            ("T"  , Ok(Tera)),  ("Ti"  , Ok(Tebi)),
499            ("P"  , Ok(Peta)),  ("Pi"  , Ok(Pebi)),
500            ("E"  , Ok(Exa )),  ("Ei"  , Ok(Exbi)),
501            #[cfg(feature = "u128")] ("Z" , Ok(Zetta)),
502            #[cfg(feature = "u128")] ("Y" , Ok(Yotta)),
503            #[cfg(feature = "u128")] ("Zi", Ok(Zebi )),
504            #[cfg(feature = "u128")] ("Yi", Ok(Yobi )),
505            #[cfg(feature = "case-insensitive")] ("k" , Ok(Kilo)),
506            #[cfg(feature = "case-insensitive")] ("ki", Ok(Kibi)),
507            #[cfg(feature = "case-insensitive")] ("m" , Ok(Mega)),
508            #[cfg(feature = "case-insensitive")] ("mi", Ok(Mebi)),
509            #[cfg(feature = "case-insensitive")] ("g" , Ok(Giga)),
510            #[cfg(feature = "case-insensitive")] ("gi", Ok(Gibi)),
511            #[cfg(feature = "case-insensitive")] ("t" , Ok(Tera)),
512            #[cfg(feature = "case-insensitive")] ("ti", Ok(Tebi)),
513            #[cfg(feature = "case-insensitive")] ("p" , Ok(Peta)),
514            #[cfg(feature = "case-insensitive")] ("pi", Ok(Pebi)),
515            #[cfg(feature = "case-insensitive")] ("e" , Ok(Exa )),
516            #[cfg(feature = "case-insensitive")] ("ei", Ok(Exbi)),
517            #[cfg(feature = "case-insensitive")] #[cfg(feature = "u128")] ("z" , Ok(Zetta)),
518            #[cfg(feature = "case-insensitive")] #[cfg(feature = "u128")] ("y" , Ok(Yotta)),
519            #[cfg(feature = "case-insensitive")] #[cfg(feature = "u128")] ("zi", Ok(Zebi )),
520            #[cfg(feature = "case-insensitive")] #[cfg(feature = "u128")] ("yi", Ok(Yobi )),
521            #[cfg(feature = "case-insensitive")] ("kI", Ok(Kibi)),
522            #[cfg(feature = "case-insensitive")] ("KI", Ok(Kibi)),
523            #[cfg(feature = "case-insensitive")] ("mI", Ok(Mebi)),
524            #[cfg(feature = "case-insensitive")] ("MI", Ok(Mebi)),
525            #[cfg(feature = "case-insensitive")] ("gI", Ok(Gibi)),
526            #[cfg(feature = "case-insensitive")] ("GI", Ok(Gibi)),
527            #[cfg(feature = "case-insensitive")] ("tI", Ok(Tebi)),
528            #[cfg(feature = "case-insensitive")] ("TI", Ok(Tebi)),
529            #[cfg(feature = "case-insensitive")] ("pI", Ok(Pebi)),
530            #[cfg(feature = "case-insensitive")] ("PI", Ok(Pebi)),
531            #[cfg(feature = "case-insensitive")] ("eI", Ok(Exbi)),
532            #[cfg(feature = "case-insensitive")] ("EI", Ok(Exbi)),
533            #[cfg(feature = "case-insensitive")] #[cfg(feature = "u128")] ("zI", Ok(Zebi)),
534            #[cfg(feature = "case-insensitive")] #[cfg(feature = "u128")] ("ZI", Ok(Zebi)),
535            #[cfg(feature = "case-insensitive")] #[cfg(feature = "u128")] ("yI", Ok(Yobi)),
536            #[cfg(feature = "case-insensitive")] #[cfg(feature = "u128")] ("YI", Ok(Yobi)),
537        ];
538
539        assert_eq!(Err(ParseError::EmptyInput), "".parse::<UnitPrefix>());
540
541        for (value, unit) in map.iter() {
542            assert_eq!(*unit, value.parse::<UnitPrefix>());
543        }
544
545        #[cfg(not(feature = "case-insensitive"))]
546        {
547            #[rustfmt::skip]
548            let invalid_formats = [
549                     "ki", "m", "mi", "g", "gi",
550                "t", "ti", "p", "pi", "e", "ei",
551                #[cfg(feature = "u128")] "z" ,
552                #[cfg(feature = "u128")] "zi",
553                #[cfg(feature = "u128")] "y" ,
554                #[cfg(feature = "u128")] "yi",
555            ];
556
557            for value in invalid_formats.iter() {
558                assert_eq!(
559                    Err(ParseError::InvalidPrefixCaseFormat),
560                    value.parse::<UnitPrefix>()
561                );
562            }
563
564            #[rustfmt::skip]
565            let invalid_prefixes = [
566                "kI", "KI", "mI", "MI", "gI", "GI",
567                "tI", "TI", "pI", "PI", "eI", "EI",
568                #[cfg(feature = "u128")] "zI" ,
569                #[cfg(feature = "u128")] "ZI",
570                #[cfg(feature = "u128")] "yI" ,
571                #[cfg(feature = "u128")] "YI",
572            ];
573
574            for value in invalid_prefixes.iter() {
575                assert_eq!(Err(ParseError::InvalidPrefix), value.parse::<UnitPrefix>());
576            }
577        }
578    }
579
580    #[test]
581    fn effective_value() {
582        #[rustfmt::skip]
583        let map = [
584            (Kilo, 1000),                 (Kibi, 1024),
585            (Mega, 1000000),              (Mebi, 1048576),
586            (Giga, 1000000000),           (Gibi, 1073741824),
587            (Tera, 1000000000000),        (Tebi, 1099511627776),
588            (Peta, 1000000000000000),     (Pebi, 1125899906842624),
589            (Exa , 1000000000000000000),  (Exbi, 1152921504606846976),
590            #[cfg(feature = "u128")] (Zetta, 1000000000000000000000),
591            #[cfg(feature = "u128")] (Yotta, 1000000000000000000000000),
592            #[cfg(feature = "u128")] (Zebi , 1180591620717411303424),
593            #[cfg(feature = "u128")] (Yobi , 1208925819614629174706176)
594        ];
595
596        for (prefix, value) in map.iter() {
597            assert_eq!(
598                *value,
599                prefix.effective_value(),
600                "expected [{:?}] to have the value [{}]",
601                prefix,
602                value
603            );
604        }
605    }
606
607    #[test]
608    fn min_max() {
609        assert_eq!(Kilo, UnitPrefix::MIN);
610        #[cfg(feature = "u128")]
611        assert_eq!(Yobi, UnitPrefix::MAX);
612        #[cfg(not(feature = "u128"))]
613        assert_eq!(Exbi, UnitPrefix::MAX);
614    }
615}