read_url/mock/
mock_url.rs

1use super::super::{context::*, url::*, util::*};
2
3use {kutil::io::reader::*, std::fmt};
4
5//
6// MockUrl
7//
8
9/// A standalone URL implementation intended for testing purposes.
10///
11/// You can set a URL representation as you please, mocking any other scheme or not
12/// following the URL notation at all. Thus mock URLs must be explictly created via
13/// [UrlContext::mock_url] and cannot be returned by general [UrlContext] functions.
14///
15/// The [URL::base] and [URL::relative] functions are supported in two modes. When
16/// slashable is true, they will interpret the URL representation as a Unix-style filesystem
17/// path, whereby the path separator is "/", and "." and ".." are supported for path
18/// traversal. When slashable is false, [URL::relative] does simple string concatenation,
19/// and you must explicitly provide a base_url_representation if you want to support [URL::base].
20/// For both functions, the content and format are simply cloned.
21///
22/// [URL::conform] does nothing.
23///
24/// For custom URLs that are supported by general [UrlContext] functions, see
25/// [InternalUrl](super::super::internal::InternalUrl).
26#[derive(Clone, Debug)]
27pub struct MockUrl {
28    /// The URL representation.
29    pub url_representation: String,
30
31    /// Whether the URL representation is "slashable".
32    pub slashable: bool,
33
34    /// The optional base URL representation (used when slashable is false).
35    pub base_url_representation: Option<String>,
36
37    /// The optional query.
38    pub query: Option<UrlQuery>,
39
40    /// The optional fragment.
41    pub fragment: Option<String>,
42
43    /// The optional format.
44    pub format: Option<String>,
45
46    /// The optional content.
47    pub content: Option<ReadableBuffer>,
48
49    pub(crate) context: UrlContextRef,
50}
51
52impl MockUrl {
53    /// Constructor.
54    pub fn new(
55        context: &UrlContextRef,
56        url_representation: String,
57        slashable: bool,
58        base_url_representation: Option<String>,
59        query: Option<UrlQuery>,
60        fragment: Option<String>,
61        format: Option<String>,
62        content: Option<&[u8]>,
63    ) -> Self {
64        Self {
65            url_representation,
66            slashable,
67            base_url_representation,
68            query,
69            fragment,
70            format,
71            content: content.map(ReadableBuffer::new),
72            context: context.clone(),
73        }
74    }
75
76    /// Constructor.
77    pub fn new_with(&self, url_representation: String) -> MockUrl {
78        Self {
79            context: self.context.clone(),
80            url_representation,
81            slashable: self.slashable,
82            query: None,
83            fragment: None,
84            format: self.format.clone(),
85            content: self.content.clone(),
86            base_url_representation: None,
87        }
88    }
89}
90
91impl fmt::Display for MockUrl {
92    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
93        let query = url_query_string(&self.query);
94        let fragment = url_fragment_string(&self.fragment);
95        write!(formatter, "{}{}{}", self.url_representation, query, fragment)
96    }
97}
98
99// Conversions
100
101impl Into<UrlRef> for MockUrl {
102    fn into(self) -> UrlRef {
103        Box::new(self)
104    }
105}