1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//! This crate revolves around the [DigitSequence] struct,
//! a sequence of 0-9 [u8] digits, with:
//!
//! * conversions from/to integers, numeric sequences and strings
//!
//! * different iteration strategies
//!
//! * a custom [CrateResult] and a custom [CrateError]
//!
//! * optional [serde] I/O
//!
//! # Features
//!
//! This crate supports the following _optional_ features:
//!
//! - `serde`: enables JSON conversions via [serde](https://crates.io/crates/serde)

mod arrays;
mod integers;
mod iteration;
mod result;
mod slices;
mod strings;
mod vecs;

#[cfg(test)]
pub mod test_utils;

pub use result::*;

/// Immutable sequence of [u8] digits.
///
/// # Creation
///
/// A digit sequence is usually created via *conversions* -
/// both fallible and infallible - although a
/// [constructor](DigitSequence::new) is provided to instantiate
/// an empty sequence that is also its [Default] value.
///
/// ```
/// use digit_sequence::*;
///
/// # fn main() -> GenericResult<()> {
/// assert_eq!(DigitSequence::new(), []);
/// assert_eq!(DigitSequence::default(), []);
///
/// let sequence: DigitSequence = [3, 8, 7].try_into()?;
/// assert_eq!(sequence, [3, 8, 7]);
///
/// assert_eq!(format!("{:?}", sequence), "DigitSequence([3, 8, 7])");
///
/// # Ok(())
/// # }
/// ```
///
/// For details and more code samples, please refer to the
/// implementations of the [From] and [TryFrom] interfaces.
///
/// # Equality
///
/// Equality is firstly supported with another [DigitSequence]:
///
/// ```
/// use digit_sequence::*;
///
/// # fn main() -> GenericResult<()> {
///
/// let source = [1, 3, 5, 7, 9];
///
/// let left: DigitSequence = (&source).try_into()?;
/// let right: DigitSequence = (&source).try_into()?;
/// assert_eq!(left, right);
///
/// let other: DigitSequence = [9u8, 4u8].try_into()?;
/// assert_ne!(left, other);
///
/// # Ok(())
/// # }
/// ```
///
/// Equality is also supported for operands of other iterable types - such as
/// [[u8]], &[[u8]] or [Vec]: please, refer to the documentation for the
/// implementations of this [PartialEq].
///
///    
/// # Order
///
/// [PartialOrd] is supported for [DigitSequence] - just as expected:
///
/// ```
/// use digit_sequence::*;
///
/// # fn main() -> GenericResult<()> {
/// let short_bigger: DigitSequence = [9].try_into()?;
/// let short_smaller: DigitSequence = [4].try_into()?;
///
/// let longest: DigitSequence = [9, 7].try_into()?;
///
/// assert!(short_bigger > short_smaller);
/// assert!(short_bigger < longest);
///
/// # Ok(())
/// # }
/// ```
///
/// # Serialization
///
/// **REQUIRES FEATURE**: `serde`.
///
/// When the `serde` feature is enabled for this crate, [DigitSequence] implements the [serde::Serialize] and [serde::Deserialize] traits.
///
/// ```
/// #[cfg(feature = "my_feature")]
/// {
///     use digit_sequence::*;
///     use serde_json::{to_string, from_str};
///
///     # fn main() -> GenericResult<()> {
///     let original: DigitSequence = 9786u16.into();
///     let expected_json = "[9,7,8,6]";
///
///     let json = to_string(&original)?;
///     assert_eq!(json, expected_json);
///
///     let deserialized: DigitSequence = from_str(expected_json)?;
///     assert_eq!(deserialized, original);
///
///     # Ok(())
///     # }
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DigitSequence(pub(crate) Vec<u8>);

impl DigitSequence {
    /// Creates an empty sequence.
    ///
    /// ```
    /// use digit_sequence::DigitSequence;
    ///
    /// let sequence = DigitSequence::new();
    ///
    /// assert_eq!(sequence.iter().len(), 0);
    /// ```
    pub fn new() -> DigitSequence {
        DigitSequence(vec![])
    }

    /// Repeatable iteration over references to the digits.
    ///
    /// ```
    /// use digit_sequence::*;
    ///
    /// # fn main() -> GenericResult<()> {
    /// let source = [9, 5, 0, 2];
    /// let sequence: DigitSequence = (&source).try_into()?;
    /// let mut target: Vec<u8> = vec![];
    ///
    /// for &digit in sequence.iter() {
    ///     target.push(digit)
    /// }
    ///
    /// for &digit in sequence.iter() {
    ///     target.push(digit)
    /// }
    ///
    /// let expected_vec: Vec<u8> = [&source[..], &source[..]].concat();
    ///
    /// assert_eq!(target, expected_vec);
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn iter(&self) -> std::slice::Iter<u8> {
        self.0.iter()
    }

    /// Tells whether the sequence is empty.
    ///
    /// ```
    /// use digit_sequence::*;
    ///
    /// let empty = DigitSequence::new();
    /// assert!(empty.is_empty());
    ///
    /// let non_empty: DigitSequence = 84u8.into();
    /// assert!(!non_empty.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}