ironshield-types 0.1.41

Standardized Types, Headers, & Methods for IronShield Bindings
Documentation
use serde::{Deserialize, Serialize};

/// * `endpoint`:  The endpoint URL for the request.
/// * `timestamp`: The timestamp of the request in unix millis.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IronShieldRequest {
    pub endpoint:  String,
    pub timestamp: i64,
}

impl IronShieldRequest {
    /// Constructor for creating a new IronShieldRequest instance.
    pub fn new(
        endpoint:  String,
        timestamp: i64
    ) -> Self {
        Self { 
            endpoint,
            timestamp,
        }
    }
    
    /// Concatenates the request data into a string.
    /// 
    /// Concatenates:
    /// - `endpoint`:  as a string.
    /// - `timestamp`: as a string.
    pub fn concat_struct(&self) -> String {
        format!(
            "{}|{}",
            self.endpoint,
            self.timestamp
        )
    }
    
    /// Creates an `IronShieldRequest` from a concatenated string.
    /// 
    /// This function reverses the operation of
    /// `IronShieldRequest::concat_struct`.
    /// Expects a string in the format: "endpoint|timestamp".
    /// 
    /// # Arguments
    /// * `concat_string`: The concatenated string to parse, typically
    ///                    generated by `concat_struct()`.
    /// 
    /// # Returns
    /// * `Result<Self, String>`: A result containing the parsed
    ///                           `IronShieldRequest`
    ///                           or an error message if parsing fails.
    pub fn from_concat_struct(concat_string: &str) -> Result<Self, String> {
        let parts: Vec<&str> = concat_string.split('|').collect();

        if parts.len() != 2 {
            return Err("Invalid format, expected 'endpoint|timestamp'".to_string());
        }

        let endpoint = parts[0].to_string();
        let timestamp = parts[1].parse::<i64>()
            .map_err(|_| "Failed to parse timestamp".to_string())?;

        Ok(Self { endpoint, timestamp })
    }

    /// Encodes the response as a base64url string for HTTP header transport.
    ///
    /// This method concatenates all response fields using the established `|` delimiter
    /// format, and then base64url-encodes the result for safe transport in HTTP headers.
    ///
    /// # Returns
    /// * `String`: Base64url-encoded string ready for HTTP header use
    ///
    /// # Example
    /// ```
    /// use ironshield_types::IronShieldRequest;
    /// let request = IronShieldRequest::new("https://example.com/api".to_string(), 123456789);
    /// let header_value = request.to_base64url_header();
    /// ```
    pub fn to_base64url_header(&self) -> String {
        crate::serde_utils::concat_struct_base64url_encode(&self.concat_struct())
    }

    /// Decodes a base64url-encoded response from an HTTP header.
    ///
    /// This method reverses the `to_base64url_header()` operation by first base64url-decoding
    /// the input string and then parsing it using the established `|` delimiter format.
    ///
    /// # Arguments
    /// * `encoded_header`: The base64url-encoded string from the HTTP header.
    ///
    /// # Returns
    /// * `Result<Self, String>`: Decoded response or detailed error message.
    ///
    /// # Example
    /// ```
    /// use ironshield_types::IronShieldRequest;
    /// // Create a response and encode it.
    /// let original = IronShieldRequest::new("https://example.com/api".to_string(), 123456789);
    /// let header_value = original.to_base64url_header();
    /// // Decode it back.
    /// let decoded = IronShieldRequest::from_base64url_header(&header_value).unwrap();
    /// assert_eq!(original.endpoint, decoded.endpoint);
    /// ```
    pub fn from_base64url_header(encoded_header: &str) -> Result<Self, String> {
        // Decode using the existing serde_utils function.
        let concat_str: String = crate::serde_utils::concat_struct_base64url_decode(encoded_header.to_string())?;
        // Parse using the existing concat_struct format.
        Self::from_concat_struct(&concat_str)
    }
}