codes_common/
lib.rs

1/*!
2Support capabilities for `codes-*` packages.
3
4# Features
5
6* `build` - Tools for build scripts.
7* `csv_tools` - Tools for reading and processing CSV files, requires `build`.
8
9*/
10
11#![warn(
12    unknown_lints,
13    // ---------- Stylistic
14    absolute_paths_not_starting_with_crate,
15    elided_lifetimes_in_paths,
16    explicit_outlives_requirements,
17    macro_use_extern_crate,
18    nonstandard_style, /* group */
19    noop_method_call,
20    rust_2018_idioms,
21    single_use_lifetimes,
22    trivial_casts,
23    trivial_numeric_casts,
24    // ---------- Future
25    future_incompatible, /* group */
26    rust_2021_compatibility, /* group */
27    // ---------- Public
28    missing_debug_implementations,
29    // missing_docs,
30    unreachable_pub,
31    // ---------- Unsafe
32    unsafe_code,
33    unsafe_op_in_unsafe_fn,
34    // ---------- Unused
35    unused, /* group */
36)]
37#![deny(
38    // ---------- Public
39    exported_private_dependencies,
40    private_in_public,
41    // ---------- Deprecated
42    anonymous_parameters,
43    bare_trait_objects,
44    ellipsis_inclusive_range_patterns,
45    // ---------- Unsafe
46    deref_nullptr,
47    drop_bounds,
48    dyn_drop,
49)]
50
51use std::{
52    fmt::{Debug, Display},
53    hash::Hash,
54    str::FromStr,
55};
56
57// ------------------------------------------------------------------------------------------------
58// Public Types
59// ------------------------------------------------------------------------------------------------
60
61pub trait Code<T>: Clone + Debug + Display + FromStr + Into<T> + PartialEq + Eq + Hash {
62    fn is_valid<S>(s: S) -> bool
63    where
64        S: AsRef<str>,
65    {
66        Self::from_str(s.as_ref()).is_ok()
67    }
68}
69
70pub trait FixedLengthCode {
71    fn fixed_length() -> usize;
72}
73
74pub trait VariableLengthCode {
75    fn min_length() -> usize;
76
77    fn max_length() -> usize;
78}
79
80// ------------------------------------------------------------------------------------------------
81// Public Macros
82// ------------------------------------------------------------------------------------------------
83
84#[macro_export]
85macro_rules! code_as_str {
86    ($type_name:ty, $inner:ident) => {
87        impl $type_name {
88            fn as_str(&self) -> &str {
89                &self.$inner
90            }
91        }
92    };
93    ($type_name:ty) => {
94        impl $type_name {
95            fn as_str(&self) -> &str {
96                &self.0
97            }
98        }
99    };
100}
101
102#[macro_export]
103macro_rules! code_impl {
104    ($type_name:ty, $id_field:ident, $ltime:lifetime $id_type_ref:ty, $id_type:ty, $from_fn:ident) => {
105        impl ::std::fmt::Display for $type_name {
106            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
107                write!(f, "{}", self.as_ref())
108            }
109        }
110
111        impl ::std::convert::AsRef<$id_type_ref> for $type_name {
112            fn as_ref(&self) -> &$ltime $id_type_ref {
113                &self.$id_field()
114            }
115        }
116
117        impl ::std::ops::Deref for $type_name {
118            type Target = $id_type_ref;
119
120            fn deref(&self) -> &$ltime Self::Target {
121                &self.$id_field()
122            }
123        }
124
125        impl ::std::convert::From<$type_name> for $id_type {
126            fn from(v: $type_name) -> Self {
127                v.$id_field().$from_fn()
128            }
129        }
130
131        impl $crate::Code<$id_type> for $type_name {}
132    };
133    ($type_name:ty, $id_field:ident, $id_type_ref:ty, $id_type:ty, $from_fn:ident) => {
134        impl ::std::fmt::Display for $type_name {
135            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
136                write!(f, "{}", self.as_ref())
137            }
138        }
139
140        impl ::std::convert::AsRef<$id_type_ref> for $type_name {
141            fn as_ref(&self) -> &$id_type_ref {
142                &self.$id_field()
143            }
144        }
145
146        impl ::std::ops::Deref for $type_name {
147            type Target = $id_type_ref;
148
149            fn deref(&self) -> &Self::Target {
150                &self.$id_field()
151            }
152        }
153
154        impl ::std::convert::From<$type_name> for $id_type {
155            fn from(v: $type_name) -> Self {
156                v.$id_field().$from_fn()
157            }
158        }
159
160        impl $crate::Code<$id_type> for $type_name {}
161    };
162    ($type_name:ty, $id_field:ident, $id_type:ty) => {
163        impl ::std::fmt::Display for $type_name {
164            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
165                write!(f, "{}", self.$id_field())
166            }
167        }
168
169        impl ::std::convert::From<$type_name> for $id_type {
170            fn from(v: $type_name) -> Self {
171                v.$id_field()
172            }
173        }
174
175        impl $crate::Code<$id_type> for $type_name {}
176    };
177
178    ($type_name:ty, $id_field:ident) => {
179        code_impl!($type_name, $id_field, 'static str, String, to_string);
180    };
181
182    ($type_name:ty) => {
183        code_impl!($type_name, code, 'static str, String, to_string);
184    };
185}
186
187#[macro_export]
188macro_rules! fixed_length_code {
189    ($type_name:ty, $length:literal) => {
190        impl $crate::FixedLengthCode for $type_name {
191            fn fixed_length() -> usize {
192                $length
193            }
194        }
195    };
196}
197
198#[macro_export]
199macro_rules! variable_length_code {
200    ($type_name:ty, $min:literal, $max:literal) => {
201        impl $crate::VariableLengthCode for $type_name {
202            fn min_length() -> usize {
203                $min
204            }
205            fn max_length() -> usize {
206                $max
207            }
208        }
209    };
210}
211
212// ------------------------------------------------------------------------------------------------
213// Public Functions
214// ------------------------------------------------------------------------------------------------
215
216// ------------------------------------------------------------------------------------------------
217// Implementations
218// ------------------------------------------------------------------------------------------------
219
220// ------------------------------------------------------------------------------------------------
221// Modules
222// ------------------------------------------------------------------------------------------------
223
224pub mod error;
225pub use error::CodeParseError;
226
227#[cfg(feature = "build")]
228#[macro_use]
229pub mod build;