better_url/better_url/domain_impl/segments/subdomain.rs
1//! Implementing subdomain segment stuff for [`BetterUrl`].
2
3use super::*;
4
5/// The enum of errors [`BetterUrl::set_subdomain_segment`] can return.
6#[derive(Debug, Error)]
7pub enum SetSubdomainSegmentError {
8 /// Returned when the URL doesn't have a subdomain.
9 #[error("The URL does not have a subdomain.")]
10 UrlDoesNotHaveSubdomain,
11 /// Returned when the segment isn't found.
12 #[error("The segment wasn't found.")]
13 SegmentNotFound,
14 /// Returned when a [`SetSubdomainError`] is encountered.
15 #[error(transparent)]
16 SetSubdomainError(#[from] SetSubdomainError)
17}
18
19/// The enum of errors [`BetterUrl::insert_subdomain_segment`] can return.
20#[derive(Debug, Error)]
21pub enum InsertSubdomainSegmentError {
22 /// Returned when the URL doesn't have a subdomain.
23 #[error("The URL does not have a subdomain.")]
24 UrlDoesNotHaveSubdomain,
25 /// Returned when the segment isn't found.
26 #[error("The segment wasn't found.")]
27 SegmentNotFound,
28 /// Returned when a [`SetSubdomainError`] is encountered.
29 #[error(transparent)]
30 SetSubdomainError(#[from] SetSubdomainError)
31}
32
33impl BetterUrl {
34 /// # Examples
35 /// ```
36 /// use better_url::*;
37 ///
38 /// let url = BetterUrl::parse("https://abc.def.example.co.uk").unwrap();
39 ///
40 /// assert_eq!(url.subdomain_segment(-3), None );
41 /// assert_eq!(url.subdomain_segment(-2), Some("abc".into()));
42 /// assert_eq!(url.subdomain_segment(-1), Some("def".into()));
43 ///
44 /// assert_eq!(url.subdomain_segment( 0), Some("abc".into()));
45 /// assert_eq!(url.subdomain_segment( 1), Some("def".into()));
46 /// assert_eq!(url.subdomain_segment( 2), None );
47 /// ```
48 pub fn subdomain_segment(&self, index: isize) -> Option<&str> {
49 match index {
50 0.. => self.subdomain()?.split('.').nth(index as usize),
51 #[allow(clippy::arithmetic_side_effects, reason = "Can't happen.")]
52 ..0 => self.subdomain()?.split('.').nth_back((-index - 1) as usize)
53 }
54 }
55
56 /// Sets the specified subdomain segment.
57 /// # Errors
58 /// If the URL doesn't have a domain, returns the error [`SetSubdomainSegmentError::UrlDoesNotHaveSubdomain`].
59 ///
60 /// If the segment isn't found, returns the error [`SetSubdomainSegmentError::SegmentNotFound`].
61 ///
62 /// If the call to [`Self::set_subdomain`] returns an error, that error is returned.
63 /// # Examples
64 /// ```
65 /// use better_url::*;
66 ///
67 /// let mut url = BetterUrl::parse("https://abc.def.example.co.uk").unwrap();
68 ///
69 /// url.set_subdomain_segment(-3, Some("n3")).unwrap_err(); assert_eq!(url.host_str(), Some("abc.def.example.co.uk"));
70 /// url.set_subdomain_segment(-2, Some("n2")).unwrap (); assert_eq!(url.host_str(), Some("n2.def.example.co.uk"));
71 /// url.set_subdomain_segment(-1, Some("n1")).unwrap (); assert_eq!(url.host_str(), Some("n2.n1.example.co.uk"));
72 ///
73 /// url.set_subdomain_segment( 0, Some("p0")).unwrap (); assert_eq!(url.host_str(), Some("p0.n1.example.co.uk"));
74 /// url.set_subdomain_segment( 1, Some("p1")).unwrap (); assert_eq!(url.host_str(), Some("p0.p1.example.co.uk"));
75 /// url.set_subdomain_segment( 2, Some("p2")).unwrap_err(); assert_eq!(url.host_str(), Some("p0.p1.example.co.uk"));
76 ///
77 ///
78 ///
79 /// url.set_subdomain_segment( 0, None).unwrap(); assert_eq!(url.host_str(), Some("p1.example.co.uk"));
80 /// url.set_subdomain_segment(-1, None).unwrap(); assert_eq!(url.host_str(), Some("example.co.uk"));
81 /// ```
82 pub fn set_subdomain_segment(&mut self, index: isize, value: Option<&str>) -> Result<(), SetSubdomainSegmentError> {
83 self.set_subdomain(set_segment(
84 self.subdomain().ok_or(SetSubdomainSegmentError::UrlDoesNotHaveSubdomain)?,
85 ".", index, value, SetSubdomainSegmentError::SegmentNotFound
86 )?.as_deref())?;
87 Ok(())
88 }
89
90 /// Inserts a new subdomain segment at the specified index.
91 /// # Errors
92 /// If the URL doesn't have a domain, returns the error [`InsertSubdomainSegmentError::UrlDoesNotHaveSubdomain`].
93 ///
94 /// If the segment isn't found, returns the error [`InsertSubdomainSegmentError::SegmentNotFound`].
95 ///
96 /// If the call to [`Self::set_subdomain`] returns an error, that error is returned.
97 pub fn insert_subdomain_segment(&mut self, index: isize, value: &str) -> Result<(), InsertSubdomainSegmentError> {
98 self.set_subdomain(Some(&insert_segment(
99 self.subdomain().ok_or(InsertSubdomainSegmentError::UrlDoesNotHaveSubdomain)?,
100 ".", index, value, InsertSubdomainSegmentError::SegmentNotFound
101 )?))?;
102 Ok(())
103 }
104}