lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

version.rs (4151B)


      1 use crate::error::RadrootsSimplexSmpProtoError;
      2 use alloc::string::{String, ToString};
      3 use core::fmt;
      4 use core::str::FromStr;
      5 
      6 pub const RADROOTS_SIMPLEX_SMP_INITIAL_CLIENT_VERSION: u16 = 1;
      7 pub const RADROOTS_SIMPLEX_SMP_SERVER_HOSTNAMES_CLIENT_VERSION: u16 = 2;
      8 pub const RADROOTS_SIMPLEX_SMP_SENDER_AUTH_KEY_CLIENT_VERSION: u16 = 3;
      9 pub const RADROOTS_SIMPLEX_SMP_SHORT_LINKS_CLIENT_VERSION: u16 = 4;
     10 pub const RADROOTS_SIMPLEX_SMP_CURRENT_CLIENT_VERSION: u16 =
     11     RADROOTS_SIMPLEX_SMP_SHORT_LINKS_CLIENT_VERSION;
     12 pub const RADROOTS_SIMPLEX_SMP_INITIAL_TRANSPORT_VERSION: u16 = 6;
     13 pub const RADROOTS_SIMPLEX_SMP_AUTH_COMMANDS_TRANSPORT_VERSION: u16 = 7;
     14 pub const RADROOTS_SIMPLEX_SMP_SENDING_PROXY_TRANSPORT_VERSION: u16 = 8;
     15 pub const RADROOTS_SIMPLEX_SMP_SENDER_AUTH_KEY_TRANSPORT_VERSION: u16 = 9;
     16 pub const RADROOTS_SIMPLEX_SMP_DELETED_EVENT_TRANSPORT_VERSION: u16 = 10;
     17 pub const RADROOTS_SIMPLEX_SMP_ENCRYPTED_BLOCK_TRANSPORT_VERSION: u16 = 11;
     18 pub const RADROOTS_SIMPLEX_SMP_BLOCKED_ENTITY_TRANSPORT_VERSION: u16 = 12;
     19 pub const RADROOTS_SIMPLEX_SMP_PROXY_SERVER_HANDSHAKE_TRANSPORT_VERSION: u16 = 14;
     20 pub const RADROOTS_SIMPLEX_SMP_SHORT_LINKS_TRANSPORT_VERSION: u16 = 15;
     21 pub const RADROOTS_SIMPLEX_SMP_SERVICE_CERTS_TRANSPORT_VERSION: u16 = 16;
     22 pub const RADROOTS_SIMPLEX_SMP_NEW_NOTIFIER_CREDENTIALS_TRANSPORT_VERSION: u16 = 17;
     23 pub const RADROOTS_SIMPLEX_SMP_CURRENT_TRANSPORT_VERSION: u16 =
     24     RADROOTS_SIMPLEX_SMP_NEW_NOTIFIER_CREDENTIALS_TRANSPORT_VERSION;
     25 
     26 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     27 pub struct RadrootsSimplexSmpVersionRange {
     28     pub min: u16,
     29     pub max: u16,
     30 }
     31 
     32 impl RadrootsSimplexSmpVersionRange {
     33     pub const fn single(version: u16) -> Self {
     34         Self {
     35             min: version,
     36             max: version,
     37         }
     38     }
     39 
     40     pub fn new(min: u16, max: u16) -> Result<Self, RadrootsSimplexSmpProtoError> {
     41         if min == 0 || max == 0 || min > max {
     42             return Err(RadrootsSimplexSmpProtoError::InvalidVersionRange(
     43                 alloc::format!("{min}-{max}"),
     44             ));
     45         }
     46 
     47         Ok(Self { min, max })
     48     }
     49 
     50     pub const fn contains(&self, version: u16) -> bool {
     51         version >= self.min && version <= self.max
     52     }
     53 }
     54 
     55 impl Default for RadrootsSimplexSmpVersionRange {
     56     fn default() -> Self {
     57         Self::single(RADROOTS_SIMPLEX_SMP_CURRENT_CLIENT_VERSION)
     58     }
     59 }
     60 
     61 impl fmt::Display for RadrootsSimplexSmpVersionRange {
     62     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     63         if self.min == self.max {
     64             write!(f, "{}", self.min)
     65         } else {
     66             write!(f, "{}-{}", self.min, self.max)
     67         }
     68     }
     69 }
     70 
     71 impl FromStr for RadrootsSimplexSmpVersionRange {
     72     type Err = RadrootsSimplexSmpProtoError;
     73 
     74     fn from_str(value: &str) -> Result<Self, Self::Err> {
     75         let trimmed = value.trim();
     76         if trimmed.is_empty() {
     77             return Err(RadrootsSimplexSmpProtoError::InvalidVersionRange(
     78                 String::new(),
     79             ));
     80         }
     81 
     82         if let Some((min, max)) = trimmed.split_once('-') {
     83             let min = parse_version(min, trimmed)?;
     84             let max = parse_version(max, trimmed)?;
     85             Self::new(min, max)
     86         } else {
     87             let version = parse_version(trimmed, trimmed)?;
     88             Self::new(version, version)
     89         }
     90     }
     91 }
     92 
     93 fn parse_version(value: &str, original: &str) -> Result<u16, RadrootsSimplexSmpProtoError> {
     94     value
     95         .parse::<u16>()
     96         .map_err(|_| RadrootsSimplexSmpProtoError::InvalidVersionRange(original.to_string()))
     97 }
     98 
     99 #[cfg(test)]
    100 mod tests {
    101     use super::*;
    102 
    103     #[test]
    104     fn parses_single_version_range() {
    105         let range = "9".parse::<RadrootsSimplexSmpVersionRange>().unwrap();
    106         assert_eq!(range, RadrootsSimplexSmpVersionRange::single(9));
    107         assert_eq!(range.to_string(), "9");
    108     }
    109 
    110     #[test]
    111     fn parses_bounded_version_range() {
    112         let range = "6-9".parse::<RadrootsSimplexSmpVersionRange>().unwrap();
    113         assert_eq!(range.min, 6);
    114         assert_eq!(range.max, 9);
    115         assert!(range.contains(7));
    116         assert_eq!(range.to_string(), "6-9");
    117     }
    118 }