azure_storage_queues 0.8.0

Azure Queue Storage crate from the Azure SDK for Rust
Documentation
use crate::{prelude::*, PopReceipt};
use azure_core::{headers::Headers, prelude::*, xml::read_xml, Method, Response as AzureResponse};
use azure_storage::headers::CommonStorageResponseHeaders;
use serde::Deserialize;
use std::convert::TryInto;
use time::OffsetDateTime;

operation! {
    GetMessages,
    client: QueueClient,
    ?number_of_messages: NumberOfMessages,
    ?visibility_timeout: VisibilityTimeout
}

impl GetMessagesBuilder {
    pub fn into_future(mut self) -> GetMessages {
        Box::pin(async move {
            let mut url = self.client.messages_url()?;

            self.visibility_timeout.append_to_url_query(&mut url);
            self.number_of_messages.append_to_url_query(&mut url);

            let mut request =
                self.client
                    .finalize_request(url, Method::Get, Headers::new(), None)?;

            let response = self.client.send(&mut self.context, &mut request).await?;

            GetMessagesResponse::try_from(response).await
        })
    }
}

#[derive(Debug, Clone)]
pub struct GetMessagesResponse {
    pub common_storage_response_headers: CommonStorageResponseHeaders,
    pub messages: Vec<Message>,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Message {
    pub message_id: String,
    pub pop_receipt: String,
    #[serde(with = "azure_core::date::rfc1123")]
    pub insertion_time: OffsetDateTime,
    #[serde(with = "azure_core::date::rfc1123")]
    pub expiration_time: OffsetDateTime,
    #[serde(with = "azure_core::date::rfc1123")]
    pub time_next_visible: OffsetDateTime,
    pub dequeue_count: u64,
    pub message_text: String,
}

impl Message {
    pub fn pop_receipt(&self) -> PopReceipt {
        PopReceipt::new(self.message_id.clone(), self.pop_receipt.clone())
    }
}

impl From<Message> for PopReceipt {
    fn from(message: Message) -> Self {
        PopReceipt::new(message.message_id, message.pop_receipt)
    }
}

#[derive(Debug, Clone, Deserialize)]
struct MessageList {
    #[serde(rename = "QueueMessage", default)]
    pub messages: Vec<Message>,
}

impl GetMessagesResponse {
    fn parse_messages(body: &[u8]) -> azure_core::Result<Vec<Message>> {
        let response: MessageList = read_xml(body)?;
        Ok(response.messages)
    }

    async fn try_from(response: AzureResponse) -> azure_core::Result<Self> {
        let (_, headers, body) = response.deconstruct();
        let body = body.collect().await?;

        let messages = Self::parse_messages(&body)?;

        Ok(GetMessagesResponse {
            common_storage_response_headers: (&headers).try_into()?,
            messages,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_messages() -> azure_core::Result<()> {
        let message = b"\xef\xbb\xbf\
             <?xml version=\"1.0\" encoding=\"utf-8\"?>\
            <QueueMessagesList><QueueMessage>\
            <MessageId>00000000-0000-0000-0000-000000000000</MessageId>\
            <InsertionTime>Mon, 27 Jun 2022 13:38:48 GMT</InsertionTime>\
            <ExpirationTime>Mon, 04 Jul 2022 13:38:48 GMT</ExpirationTime>\
            <PopReceipt>REDACTED1</PopReceipt>\
            <TimeNextVisible>Mon, 27 Jun 2022 13:38:53 GMT</TimeNextVisible>\
            <DequeueCount>1</DequeueCount>\
            <MessageText>test1</MessageText>\
            </QueueMessage>\
            <QueueMessage>\
            <MessageId>11111111-1111-1111-1111-111111111111</MessageId>\
            <InsertionTime>Mon, 27 Jun 2022 13:38:48 GMT</InsertionTime>\
            <ExpirationTime>Mon, 04 Jul 2022 13:38:48 GMT</ExpirationTime>\
            <PopReceipt>REDACTED2</PopReceipt>\
            <TimeNextVisible>Mon, 27 Jun 2022 13:38:53 GMT</TimeNextVisible>\
            <DequeueCount>1</DequeueCount>\
            <MessageText>test2</MessageText>\
            </QueueMessage>\
            </QueueMessagesList>\
            ";

        let messages = GetMessagesResponse::parse_messages(message)?;

        assert_eq!(messages.len(), 2);
        assert_eq!(messages[0].message_text, "test1");
        assert_eq!(messages[1].message_text, "test2");

        Ok(())
    }
}