Skip to main content

num_err/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3#![cfg(feature = "alloc")]
4extern crate alloc;
5
6/// If you are lazy or because of performance did not  specified different cases.
7#[derive(Debug, Clone, Copy)]
8pub struct MathError;
9
10impl core::fmt::Display for MathError {
11    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12        write!(f, "MathError")
13    }
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, Copy)]
17pub enum MathErrors {
18    InvalidInput,
19    Overflow,
20    Underflow,
21    DivisionByZero,
22}
23
24#[derive(Debug, Clone, Copy)]
25pub struct MathErrorsInvalidInput;
26
27impl core::fmt::Display for MathErrorsInvalidInput {
28    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
29        write!(f, "InvalidInput")
30    }
31}
32
33#[derive(Debug, Clone, Copy)]
34pub struct MathErrorsOverflow;
35
36impl core::fmt::Display for MathErrorsOverflow {
37    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38        write!(f, "Overflow")
39    }
40}
41
42#[derive(Debug, Clone, Copy)]
43pub struct MathErrorsUnderflow;
44
45impl core::fmt::Display for MathErrorsUnderflow {
46    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
47        write!(f, "Underflow")
48    }
49}
50#[derive(Debug, Clone, Copy)]
51pub struct MathErrorsDivisionByZero;
52
53impl core::fmt::Display for MathErrorsDivisionByZero {
54    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55        write!(f, "DivisionByZero")
56    }
57}
58
59impl From<MathErrorsInvalidInput> for MathError {
60    fn from(_: MathErrorsInvalidInput) -> Self {
61        MathError
62    }
63}
64
65impl From<MathErrorsInvalidInput> for MathErrors {
66    fn from(_: MathErrorsInvalidInput) -> Self {
67        MathErrors::InvalidInput
68    }
69}
70
71impl From<MathErrorsOverflow> for MathErrors {
72    fn from(_: MathErrorsOverflow) -> Self {
73        MathErrors::Overflow
74    }
75}
76
77impl From<MathErrorsUnderflow> for MathErrors {
78    fn from(_: MathErrorsUnderflow) -> Self {
79        MathErrors::Underflow
80    }
81}
82
83impl From<MathErrorsDivisionByZero> for MathErrors {
84    fn from(_: MathErrorsDivisionByZero) -> Self {
85        MathErrors::DivisionByZero
86    }
87}
88
89impl From<MathErrorsOverflow> for MathError {
90    fn from(_: MathErrorsOverflow) -> Self {
91        MathError
92    }
93}
94
95impl From<MathErrorsUnderflow> for MathError {
96    fn from(_: MathErrorsUnderflow) -> Self {
97        MathError
98    }
99}
100
101impl From<MathErrorsDivisionByZero> for MathError {
102    fn from(_: MathErrorsDivisionByZero) -> Self {
103        MathError
104    }
105}
106
107impl core::fmt::Display for MathErrors {
108    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
109        match self {
110            MathErrors::InvalidInput => write!(f, "InvalidInput"),
111            MathErrors::Overflow => write!(f, "Overflow"),
112            MathErrors::Underflow => write!(f, "Underflow"),
113            MathErrors::DivisionByZero => write!(f, "Division"),
114        }
115    }
116}
117
118impl Into<u8> for MathErrors {
119    fn into(self) -> u8 {
120        self.to_primitive()
121    }
122}
123
124impl MathErrors {
125    pub const fn is_invalid_input(&self) -> bool {
126        matches!(self, MathErrors::InvalidInput)
127    }
128
129    pub const fn is_overflow(&self) -> bool {
130        matches!(self, MathErrors::Overflow)
131    }
132
133    pub const fn is_underflow(&self) -> bool {
134        matches!(self, MathErrors::Underflow)
135    }
136
137    pub const fn is_division_by_zero(&self) -> bool {
138        matches!(self, MathErrors::DivisionByZero)
139    }
140
141    pub const fn to_primitive(&self) -> u8 {
142        match self {
143            MathErrors::InvalidInput => 0,
144            MathErrors::Overflow => 1,
145            MathErrors::Underflow => 2,
146            MathErrors::DivisionByZero => 3,
147        }
148    }
149
150    pub const fn try_from_primitive(value: u8) -> Option<Self> {
151        match value {
152            0 => Some(MathErrors::InvalidInput),
153            1 => Some(MathErrors::Overflow),
154            2 => Some(MathErrors::Underflow),
155            3 => Some(MathErrors::DivisionByZero),
156            _ => None,
157        }
158    }
159
160    pub const fn to_str(&self) -> &'static str {
161        match self {
162            MathErrors::InvalidInput => "InvalidInput",
163            MathErrors::Overflow => "Overflow",
164            MathErrors::Underflow => "Underflow",
165            MathErrors::DivisionByZero => "DivisionByZero",
166        }
167    }
168}
169
170impl TryFrom<u8> for MathErrors {
171    type Error = &'static str;
172
173    fn try_from(value: u8) -> Result<Self, Self::Error> {
174        Self::try_from_primitive(value).ok_or("Must be in range 0..=3")
175    }
176}
177
178impl From<MathErrors> for MathError {
179    fn from(_: MathErrors) -> Self {
180        MathError
181    }
182}
183
184impl core::str::FromStr for MathErrors {
185    type Err = &'static str;
186
187    fn from_str(s: &str) -> Result<Self, Self::Err> {
188        match s {
189            "InvalidInput" => Ok(MathErrors::InvalidInput),
190            "Overflow" => Ok(MathErrors::Overflow),
191            "Underflow" => Ok(MathErrors::Underflow),
192            "DivisionByZero" => Ok(MathErrors::DivisionByZero),
193            _ => Err("InvalidInput, Overlow, Underflow, or DivisionByZero"),
194        }
195    }
196}
197
198/// Serializes to and from string.
199#[cfg(feature = "serde1")]
200mod serde1_impl {
201    use super::*;
202    use serde1::{de::Visitor, Deserialize, Serialize};
203
204    impl Serialize for MathErrors {
205        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
206        where
207            S: serde1::Serializer,
208        {
209            serializer.serialize_str(self.to_str())
210        }
211    }
212
213    impl<'de> Deserialize<'de> for MathErrors {
214        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
215        where
216            D: serde1::Deserializer<'de>,
217        {
218            use core::fmt;
219            struct SelfVisitor;
220            impl Visitor<'_> for SelfVisitor {
221                type Value = MathErrors;
222
223                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
224                    // exepcts one of enum string values
225                    write!(
226                        formatter,
227                        "InvalidInput, Overflow, Underflow, or DivisionByZero"
228                    )
229                }
230
231                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
232                where
233                    E: serde1::de::Error,
234                {
235                    match v {
236                        "InvalidInput" => Ok(MathErrors::InvalidInput),
237                        "Overflow" => Ok(MathErrors::Overflow),
238                        "Underflow" => Ok(MathErrors::Underflow),
239                        "DivisionByZero" => Ok(MathErrors::DivisionByZero),
240                        _ => Err(E::invalid_value(
241                            serde1::de::Unexpected::Str(v),
242                            &"InvalidInput, Overlow, Underflow, or DivisionByZero",
243                        )),
244                    }
245                }
246            }
247
248            deserializer.deserialize_str(SelfVisitor)
249        }
250    }
251
252    #[cfg(feature = "schemars1")]
253    mod schemars1_impl {
254        use super::*;
255        use schemars1::{json_schema, JsonSchema};
256
257        impl JsonSchema for MathErrors {
258            fn schema_name() -> alloc::borrow::Cow<'static, str> {
259                "MathErrors".into()
260            }
261
262            fn json_schema(_generator: &mut schemars1::SchemaGenerator) -> schemars1::Schema {
263                json_schema!(
264                    {
265                        "description": "Simple math error",
266                        "type": ["string"],
267                        "enum": [
268                            "InvalidInput",
269                            "Overflow",
270                            "Underflow",
271                            "DivisionByZero"
272                            ],
273                        "maxLength": 14,
274                        "minLength": 8,
275                    }
276                )
277            }
278        }
279    }
280}
281
282#[cfg(feature = "borsh1")]
283mod borsh1 {
284    use borsh1::{BorshDeserialize, BorshSerialize};
285
286    use crate::MathErrors;
287
288    impl BorshDeserialize for MathErrors {
289        fn deserialize_reader<R: borsh1::io::Read>(reader: &mut R) -> borsh1::io::Result<Self> {
290            let value = u8::deserialize_reader(reader)?;
291            Self::try_from_primitive(value).ok_or(borsh1::io::ErrorKind::InvalidData.into())
292        }
293    }
294
295    impl BorshSerialize for MathErrors {
296        fn serialize<W: borsh1::io::Write>(&self, writer: &mut W) -> borsh1::io::Result<()> {
297            self.to_primitive().serialize(writer)
298        }
299    }
300
301    #[cfg(feature = "borsh1_unstable__schema")]
302    #[allow(non_snake_case)]
303    mod borsh1_unstable__schema_impl {
304        use super::super::{
305            MathErrorsDivisionByZero, MathErrorsInvalidInput, MathErrorsOverflow,
306            MathErrorsUnderflow,
307        };
308        use super::*;
309        use alloc::string::ToString;
310        use borsh1::{
311            schema::{Definition, Fields},
312            BorshSchema,
313        };
314        impl BorshSchema for MathErrorsInvalidInput {
315            fn add_definitions_recursively(
316                definitions: &mut alloc::collections::btree_map::BTreeMap<
317                    borsh1::schema::Declaration,
318                    Definition,
319                >,
320            ) {
321                definitions.insert(
322                    Self::declaration(),
323                    Definition::Struct {
324                        fields: Fields::Empty,
325                    },
326                );
327            }
328
329            fn declaration() -> borsh1::schema::Declaration {
330                "MathErrorsInvalidInput".to_string()
331            }
332        }
333
334        impl BorshSchema for MathErrorsOverflow {
335            fn add_definitions_recursively(
336                definitions: &mut alloc::collections::btree_map::BTreeMap<
337                    borsh1::schema::Declaration,
338                    Definition,
339                >,
340            ) {
341                definitions.insert(
342                    Self::declaration(),
343                    Definition::Struct {
344                        fields: Fields::Empty,
345                    },
346                );
347            }
348
349            fn declaration() -> borsh1::schema::Declaration {
350                "MathErrorsOverflow".to_string()
351            }
352        }
353
354        impl BorshSchema for MathErrorsUnderflow {
355            fn add_definitions_recursively(
356                definitions: &mut alloc::collections::btree_map::BTreeMap<
357                    borsh1::schema::Declaration,
358                    Definition,
359                >,
360            ) {
361                definitions.insert(
362                    Self::declaration(),
363                    Definition::Struct {
364                        fields: Fields::Empty,
365                    },
366                );
367            }
368
369            fn declaration() -> borsh1::schema::Declaration {
370                "MathErrorsUnderflow".to_string()
371            }
372        }
373
374        impl BorshSchema for MathErrorsDivisionByZero {
375            fn add_definitions_recursively(
376                definitions: &mut alloc::collections::btree_map::BTreeMap<
377                    borsh1::schema::Declaration,
378                    Definition,
379                >,
380            ) {
381                definitions.insert(
382                    Self::declaration(),
383                    Definition::Struct {
384                        fields: Fields::Empty,
385                    },
386                );
387            }
388
389            fn declaration() -> borsh1::schema::Declaration {
390                "MathErrorsDivisionByZero".to_string()
391            }
392        }
393
394        impl BorshSchema for MathErrors {
395            fn add_definitions_recursively(
396                definitions: &mut alloc::collections::btree_map::BTreeMap<
397                    borsh1::schema::Declaration,
398                    borsh1::schema::Definition,
399                >,
400            ) {
401                MathErrorsInvalidInput::add_definitions_recursively(definitions);
402                MathErrorsOverflow::add_definitions_recursively(definitions);
403                MathErrorsUnderflow::add_definitions_recursively(definitions);
404                MathErrorsDivisionByZero::add_definitions_recursively(definitions);
405
406                let definition = Definition::Enum {
407                    tag_width: 1,
408                    variants: alloc::vec![
409                        (
410                            0,
411                            "InvalidInput".to_string(),
412                            <MathErrorsInvalidInput as BorshSchema>::declaration()
413                        ),
414                        (
415                            1,
416                            "Overflow".to_string(),
417                            <MathErrorsOverflow as BorshSchema>::declaration()
418                        ),
419                        (
420                            2,
421                            "Underflow".to_string(),
422                            <MathErrorsUnderflow as BorshSchema>::declaration()
423                        ),
424                        (
425                            3,
426                            "DivisionByZero".to_string(),
427                            <MathErrorsDivisionByZero as BorshSchema>::declaration()
428                        ),
429                    ],
430                };
431
432                match definitions.entry(Self::declaration()) {
433                    alloc::collections::btree_map::Entry::Vacant(vacant_entry) => {
434                        vacant_entry.insert(definition);
435                    }
436                    alloc::collections::btree_map::Entry::Occupied(occupied_entry) => {
437                        let other = occupied_entry.get();
438                        assert_eq!(&definition, other, "definition must be same shape");
439                    }
440                }
441            }
442
443            fn declaration() -> borsh1::schema::Declaration {
444                "MathErrors".to_string()
445            }
446        }
447    }
448}
449
450#[cfg(feature = "protobuf3")]
451mod protobuf3_impl {
452    use crate::*;
453    use protobuf3::Enum;
454
455    #[allow(clippy::derivable_impls)]
456    impl Default for MathErrors {
457        fn default() -> Self {
458            MathErrors::InvalidInput
459        }
460    }
461
462    impl Enum for MathErrors {
463        const NAME: &'static str = "MathErrors";
464
465        fn value(&self) -> i32 {
466            self.to_primitive().into()
467        }
468
469        fn from_i32(v: i32) -> Option<Self> {
470            match v {
471                0 => Some(Self::InvalidInput),
472                2 => Some(Self::Overflow),
473                3 => Some(Self::Underflow),
474                4 => Some(Self::DivisionByZero),
475                _ => None,
476            }
477        }
478
479        fn from_str(s: &str) -> Option<Self> {
480            match s {
481                "InvalidInput" => Some(Self::InvalidInput),
482                "Overflow" => Some(Self::Overflow),
483                "Underflow" => Some(Self::Underflow),
484                "DivisionByZero" => Some(Self::DivisionByZero),
485                _ => None,
486            }
487        }
488        const VALUES: &'static [Self] = &[
489            Self::InvalidInput,
490            Self::Overflow,
491            Self::Underflow,
492            Self::DivisionByZero,
493        ];
494    }
495}
496
497#[cfg(feature = "parity-scale-codec3")]
498mod parity_scale_codec3_impl {
499    use super::*;
500    use parity_scale_codec3::Encode;
501
502    impl Encode for MathErrors {
503        fn size_hint(&self) -> usize {
504            1
505        }
506
507        fn encode_to<T: parity_scale_codec3::Output + ?Sized>(&self, dest: &mut T) {
508            dest.push_byte(self.to_primitive());
509        }
510
511        fn encoded_size(&self) -> usize {
512            1
513        }
514    }
515}
516
517#[cfg(feature = "proptest1")]
518mod proptest1_impl {
519    use super::*;
520    use proptest1::{
521        prelude::{Arbitrary, BoxedStrategy, Just, Strategy},
522        prop_oneof,
523    };
524
525    impl Arbitrary for MathErrors {
526        type Parameters = ();
527        type Strategy = BoxedStrategy<Self>;
528
529        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
530            prop_oneof![
531                Just(Self::Overflow),
532                Just(Self::Underflow),
533                Just(Self::DivisionByZero),
534            ]
535            .boxed()
536        }
537    }
538}
539
540#[cfg(feature = "arbitrary1")]
541mod arbitrary1_impl {
542    use super::*;
543    use arbitrary1::*;
544
545    impl<'a> Arbitrary<'a> for MathErrors {
546        fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
547            let value = u.int_in_range(0..=3)?;
548            Ok(Self::try_from_primitive(value).expect("with in range"))
549        }
550    }
551}
552
553#[cfg(feature = "arbitrary-int1")]
554mod arbitrary_int1_impl {
555    use super::*;
556    use arbitrary_int1::u2;
557
558    impl MathErrors {
559        pub const fn from_u2(value: u2) -> Self {
560            match value.value() {
561                0 => MathErrors::InvalidInput,
562                1 => MathErrors::Overflow,
563                2 => MathErrors::Underflow,
564                _ => MathErrors::DivisionByZero,
565            }
566        }
567
568        pub const fn to_primitive_u2(&self) -> u2 {
569            match self {
570                MathErrors::InvalidInput => u2::new(0),
571                MathErrors::Overflow => u2::new(1),
572                MathErrors::Underflow => u2::new(2),
573                MathErrors::DivisionByZero => u2::new(3),
574            }
575        }
576    }
577
578    impl Into<u2> for MathErrors {
579        fn into(self) -> u2 {
580            self.to_primitive_u2()
581        }
582    }
583
584    impl From<u2> for MathErrors {
585        fn from(value: u2) -> Self {
586            Self::from_u2(value)
587        }
588    }
589}
590
591#[cfg(feature = "error")]
592mod error_impl {
593    use super::*;
594    use core::error::Error;
595    impl Error for MathErrors {}
596
597    impl Error for MathError {}
598
599    impl Error for MathErrorsInvalidInput {}
600
601    impl Error for MathErrorsOverflow {}
602
603    impl Error for MathErrorsUnderflow {}
604
605    impl Error for MathErrorsDivisionByZero {}
606}