libsignal-rust 0.1.0

Complete and Powerful Rust implementation of libsignal protocol
Documentation
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProtocolAddress {
    pub id: String,
    pub device_id: u32,
}

impl ProtocolAddress {
    pub fn from_string(encoded_address: &str) -> Result<Self, Box<dyn std::error::Error>> {
        Self::from_encoded(encoded_address)
    }

    pub fn from_encoded(encoded_address: &str) -> Result<Self, Box<dyn std::error::Error>> {
        if encoded_address.matches('.').count() != 1 {
            return Err("Invalid address encoding: must contain exactly one '.' character".into());
        }
        
        let parts: Vec<&str> = encoded_address.split('.').collect();
        if parts.len() != 2 {
            return Err("Invalid address encoding: must have exactly two parts separated by '.'".into());
        }
        
        if parts[0].is_empty() {
            return Err("Invalid address encoding: ID part cannot be empty".into());
        }
        
        let device_id = parts[1].parse::<u32>()
            .map_err(|_| "Invalid device ID: must be a valid 32-bit unsigned integer")?;
        
        Self::new(parts[0].to_string(), device_id)
    }

    pub fn new(id: String, device_id: u32) -> Result<Self, Box<dyn std::error::Error>> {
        if id.contains('.') {
            return Err("ProtocolAddress ID cannot contain '.' character - use from_encoded() for encoded addresses".into());
        }
        Ok(Self { id, device_id })
    }

    pub fn to_string(&self) -> String {
        format!("{}.{}", self.id, self.device_id)
    }

    pub fn is(&self, other: &Self) -> bool {
        self.id == other.id && self.device_id == other.device_id
    }
}