url.rs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Copyright (c) 2022-2023 Yuki Kishimoto
  2. // Distributed under the MIT software license
  3. //! Url
  4. use core::fmt;
  5. use core::str::FromStr;
  6. use serde::{Deserialize, Serialize};
  7. use thiserror::Error;
  8. use url::{ParseError, Url};
  9. /// Url Error
  10. #[derive(Debug, Error, PartialEq, Eq)]
  11. pub enum Error {
  12. /// Url error
  13. #[error("`{0}`")]
  14. Url(#[from] ParseError),
  15. }
  16. /// Unchecked Url
  17. #[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
  18. pub struct UncheckedUrl(String);
  19. impl UncheckedUrl {
  20. /// New unchecked url
  21. pub fn new<S>(url: S) -> Self
  22. where
  23. S: Into<String>,
  24. {
  25. Self(url.into())
  26. }
  27. /// Empty unchecked url
  28. pub fn empty() -> Self {
  29. Self(String::new())
  30. }
  31. pub fn join(&self, path: &str) -> Result<Url, Error> {
  32. let url: Url = self.try_into()?;
  33. Ok(url.join(path)?)
  34. }
  35. }
  36. impl<S> From<S> for UncheckedUrl
  37. where
  38. S: Into<String>,
  39. {
  40. fn from(url: S) -> Self {
  41. Self(url.into())
  42. }
  43. }
  44. impl FromStr for UncheckedUrl {
  45. type Err = Error;
  46. fn from_str(url: &str) -> Result<Self, Self::Err> {
  47. Ok(Self::from(url))
  48. }
  49. }
  50. impl TryFrom<UncheckedUrl> for Url {
  51. type Error = Error;
  52. fn try_from(unchecked_url: UncheckedUrl) -> Result<Url, Self::Error> {
  53. Ok(Self::parse(&unchecked_url.0)?)
  54. }
  55. }
  56. impl TryFrom<&UncheckedUrl> for Url {
  57. type Error = Error;
  58. fn try_from(unchecked_url: &UncheckedUrl) -> Result<Url, Self::Error> {
  59. Ok(Self::parse(unchecked_url.0.as_str())?)
  60. }
  61. }
  62. impl fmt::Display for UncheckedUrl {
  63. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  64. write!(f, "{}", self.0)
  65. }
  66. }
  67. #[cfg(test)]
  68. mod tests {
  69. use super::*;
  70. #[test]
  71. fn test_unchecked_relay_url() {
  72. let relay = "wss://relay.damus.io:8333/";
  73. let unchecked_relay_url = UncheckedUrl::from_str(relay).unwrap();
  74. assert_eq!(relay, unchecked_relay_url.to_string());
  75. // assert_eq!(relay, serde_json::to_string(&unchecked_relay_url).unwrap());
  76. let relay = "wss://relay.damus.io:8333";
  77. let unchecked_relay_url = UncheckedUrl::from_str(relay).unwrap();
  78. assert_eq!(relay, unchecked_relay_url.to_string());
  79. // assert_eq!(relay,
  80. // serde_json::to_string(&unchecked_relay_url).unwrap())
  81. }
  82. }