parse-sap-atom-feed 1.3.0

Parse an XML atom:Feed received from an SAP V2 OData service using code generated by crate parse-sap-odata
Documentation
use super::{to_naive_date_time, to_naive_date_time_opt};
use crate::test_utils::*;
use std::fmt::{Display, Formatter};

use serde::Deserialize;
use std::str::FromStr;

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Tests for DateTime deserialization
#[derive(Deserialize, PartialEq, Debug)]
#[serde(rename_all = "PascalCase")]
struct DateElement {
    #[serde(deserialize_with = "to_naive_date_time")]
    created_at: chrono::NaiveDateTime,
}

impl Display for DateElement {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self.created_at)
    }
}

impl FromStr for DateElement {
    type Err = quick_xml::de::DeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        quick_xml::de::from_str(s)
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[derive(Deserialize, PartialEq, Debug)]
#[serde(rename_all = "PascalCase")]
struct OptionalDateElement {
    #[serde(deserialize_with = "to_naive_date_time_opt")]
    created_at: Option<chrono::NaiveDateTime>,
}

impl FromStr for OptionalDateElement {
    type Err = quick_xml::de::DeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        quick_xml::de::from_str(s)
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[test]
fn should_deserialize_naive_date_time() -> Result<(), String> {
    let test_date_time = "2023-08-31T07:11:03.1182110";
    let created_at = chrono::NaiveDateTime::from_str(test_date_time).unwrap();
    let created_at_xml = &format!("<Test><d:CreatedAt>{}</d:CreatedAt></Test>", test_date_time);

    match DateElement::from_str(created_at_xml) {
        Ok(result) => handle_test_comparison(&created_at, &result.created_at),
        Err(err) => Err(err.to_string()),
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[test]
fn should_deserialize_optional_naive_date_time() -> Result<(), String> {
    let test_date_time = "2023-08-31T07:11:03.1182110";
    let created_at = chrono::NaiveDateTime::from_str(test_date_time).unwrap();
    let created_at_xml = &format!("<Test><d:CreatedAt>{}</d:CreatedAt></Test>", test_date_time);

    match OptionalDateElement::from_str(created_at_xml) {
        Ok(result) => handle_test_comparison_opt(&result.created_at, &Some(created_at)),
        Err(err) => Err(err.to_string()),
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[test]
fn should_deserialize_empty_optional_naive_date_time() -> Result<(), String> {
    let created_at_xml = "<Test><d:CreatedAt m:null=\"true\" /></Test>";

    match OptionalDateElement::from_str(created_at_xml) {
        Ok(result) => handle_test_comparison_opt(&result.created_at, &None),
        Err(err) => Err(err.to_string()),
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[test]
fn should_not_deserialize_empty_naive_date_time() -> Result<(), String> {
    let expected_error = "premature end of input";
    let created_at_xml = "<Test><d:CreatedAt /></Test>";

    match DateElement::from_str(created_at_xml) {
        Ok(result) => Err(format!("Expected parse failure, but got {result}")),
        Err(err) => {
            if err.to_string().eq(expected_error) {
                Ok(())
            } else {
                Err(format!(
                    "Expected '{}', but got '{}'",
                    expected_error,
                    err.to_string()
                ))
            }
        }
    }
}