#[macro_export]
macro_rules! define_newtype_with_default_str {
    ($vis:vis, $name:ident, $default:expr) => {
        #[derive(Clone, Eq, serde::Deserialize)]
        $vis struct $name(String);

        impl ::std::cmp::PartialEq for $name {
            fn eq(&self, other: &Self) -> bool {
                self.0 == other.0
            }
        }

        impl ::std::cmp::PartialEq<&str> for $name {
            fn eq(&self, other: &&str) -> bool {
                self.0.as_str() == *other
            }
        }

        impl ::std::cmp::PartialEq<String> for $name {
            fn eq(&self, other: &String) -> bool {
                &self.0 == other
            }
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                self.0.fmt(f)
            }
        }

        impl Default for $name {
            fn default() -> Self {
                Self($default.to_string())
            }
        }

        impl From<String> for $name {
            fn from(s: String) -> Self {
                Self(s)
            }
        }

        impl From<&str> for $name {
            fn from(s: &str) -> Self {
                Self(s.to_string())
            }
        }

        impl ::std::ops::Deref for $name {
            type Target = String;

            fn deref(&self) -> &Self::Target {
                &self.0
            }
        }

        impl ::std::ops::DerefMut for $name {
            fn deref_mut(&mut self) -> &mut Self::Target {
                &mut self.0
            }
        }

        impl ::std::convert::AsRef<str> for $name {
            fn as_ref(&self) -> &str {
                &self.0
            }
        }
    };
}

#[cfg(test)]
mod tests {
    const CONST_DEFAULT: &str = "wwwrs";
    fn const_default_fn() -> &'static str {
        "WWWRS"
    }

    define_newtype_with_default_str!(pub(crate), HlsFilePath, CONST_DEFAULT);
    define_newtype_with_default_str!(pub(crate), HlsFilePath2, const_default_fn());

    #[test]
    fn test_hls_file_path() {
        let path = HlsFilePath::default();
        assert_eq!(path.as_str(), "wwwrs");
        assert_eq!(path.len(), 5);

        assert_eq!(path, HlsFilePath::from("wwwrs"));
        assert_eq!(path.to_string(), "wwwrs");
        assert_eq!(path, "wwwrs");
        assert_eq!(path, "wwwrs".to_string());

        assert_eq!(format!("{:?}", path), "\"wwwrs\"");

        let path = HlsFilePath::from("custom/path".to_string());
        assert_eq!(path.as_str(), "custom/path");

        let path = HlsFilePath::from("another/path");
        assert_eq!(path.as_str(), "another/path");

        let path = HlsFilePath::from("test/path");
        assert_eq!(*path, "test/path".to_string());

        let path = HlsFilePath::from("ref/path");
        let str_ref: &str = path.as_ref();
        assert_eq!(str_ref, "ref/path");

        assert_eq!(HlsFilePath2::default().to_string(), "WWWRS");
    }
}
