ivms101 0.1.0

A library to handle Intervasp Messaging Standard Payloads
Documentation
#[doc(hidden)]
#[macro_export]
macro_rules! constrained_string {
    ($newtype:ident, $len_check:expr) => {
        #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
        #[serde(into = "String", try_from = "&str")]
        pub struct $newtype {
            inner: String,
        }

        impl TryFrom<&str> for $newtype {
            type Error = Error;
            fn try_from(from: &str) -> Result<Self, Error> {
                if $len_check(from.len()) {
                    Ok(Self { inner: from.into() })
                } else {
                    Err(format!(
                        "Cannot parse String of length {} into a {:?}",
                        from.len(),
                        std::any::type_name::<Self>()
                    )
                    .as_str()
                    .into())
                }
            }
        }

        impl From<$newtype> for String {
            fn from(value: $newtype) -> Self {
                value.inner
            }
        }

        impl $newtype {
            #[must_use]
            pub fn as_str(&self) -> &str {
                &self.inner
            }
        }

        impl std::fmt::Display for $newtype {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                self.inner.fmt(f)
            }
        }
    };
}

#[cfg(test)]
mod tests {
    use crate::Error;

    #[test]
    fn test_max_string() {
        crate::constrained_string!(StringMax4, |l| l <= 4);

        let max4 = StringMax4::try_from("0123").unwrap();
        serde_test::assert_tokens(&max4, &[serde_test::Token::BorrowedStr("0123")]);
        assert_eq!(max4.as_str(), "0123");

        serde_test::assert_de_tokens_error::<StringMax4>(
            &[serde_test::Token::BorrowedStr("01234")],
            r#"Validation error: Cannot parse String of length 5 into a "ivms101::types::constrained_string::tests::test_max_string::StringMax4""#,
        );
    }
}