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
#![deny(missing_docs)] //! An APRS-IS passcode generator and type. //! //! # Usage //! //! The `Callpass` type is used for representing an APRS-IS passcode. //! It will transform a callsign into a passcode, as well integers, //! and can be used in place of integers where expecting a callpass. //! //! ``` //! let given_callsign = "x2yz".to_string(); //! let given_callpass = 29322i64; //! ``` //! //! We can generate a `Callpass` like so, using the From trait: //! //! ``` //! # use callpass::Callpass; //! # let given_callsign = "x2yz".to_string(); //! // This step will generate an APRS-IS passcode. //! let callpass: Callpass = given_callsign.into(); //! ``` //! //! If we already have an APRS-IS passcode as an integer, we can //! make a `Callpass` from that as well to gain the benefits of type //! checking: //! //! ``` //! # use callpass::Callpass; //! # let given_callpass = 29322i64; //! let their_callpass: Callpass = given_callpass.into(); //! //! assert!(their_callpass == given_callpass); //! ``` #[macro_use] mod impl_macro; use std::fmt::{Display, Formatter, Result}; /// This type will generate and represent an APRS-IS passcode. /// /// # Callpass generation /// /// When given a callsign, an APRS-IS passcode will be generated. /// /// ``` /// # use callpass::Callpass; /// let callpass: Callpass = "x2yz".into(); /// ``` /// /// # Comparisons /// /// Its value can be directly compared to other numbers. /// /// ``` /// # use callpass::Callpass; /// # let callpass: Callpass = "x2yz".into(); /// assert!(callpass == 29322); /// ``` /// /// # Representation /// /// A `Callpass` can also be used in place of integers. /// /// ``` /// # use callpass::Callpass; /// # let callpass: Callpass = "x2yz".into(); /// let given_passcode: Callpass = 29322.into(); /// assert!(callpass == given_passcode); /// ``` /// /// A `Callpass` can also be used as an integer where required. /// /// ``` /// # use callpass::Callpass; /// # let callpass: Callpass = "x2yz".into(); /// fn i64_eater(lunch: i64) {} /// /// i64_eater(callpass.into()) /// ``` /// /// # Modification /// /// A `Callpass` will not allow modification (without being casted). /// /// ```compile_fail /// # use callpass::Callpass; /// # let callpass: Callpass = "x2yz".into(); /// let changed_callpass = callpass + 4; /// ``` /// /// ```compile_fail /// # use callpass::Callpass; /// # let mut callpass = Callpass "x2yz".into(); /// callpass.0 = 12345; /// ``` #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct Callpass(u16); impl Callpass { fn new(callsign: &String) -> Callpass { Callpass({ let mut hash: u16 = 0x73e2; // seed value let mut i = true; // loop switch for x in callsign.chars() { let x = x.to_uppercase().next().unwrap() as u16; match i { true => hash = hash ^ x << 8, false => hash = hash ^ x, }; i = !i; } hash & 0x7fff }) } } generate_impl_into!(u16, i16, u32, i32, u64, i64); generate_impl_from!(u16, i16, u32, i32, u64, i64); generate_impl_partialeq!(u16, i16, u32, i32, u64, i64); impl Display for Callpass { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "{:05}", self.0) } } impl Into<String> for Callpass { fn into(self) -> String { self.0.to_string() } } impl From<String> for Callpass { fn from(callsign: String) -> Self { Callpass::new(&callsign) } } impl<'a> From<&'a String> for Callpass { fn from(callsign: &'a String) -> Self { Callpass::new(callsign) } } impl<'a> From<&'a str> for Callpass { fn from(callsign: &'a str) -> Self { Callpass::new(&(callsign.to_string())) } }