Skip to content

Commit fdd8c61

Browse files
committed
Add optional value support
1 parent f684b81 commit fdd8c61

File tree

4 files changed

+109
-9
lines changed

4 files changed

+109
-9
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@
33
All notable changes to this project will be documented in this file.
44
This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
55

6+
## [0.2.0] - 2023-07-07
7+
8+
### Added
9+
10+
- Added the `with_opt_value` and `push_opt` helper methods.
11+
612
## [0.1.0] - 2023-07-07
713

814
### Internal
915

1016
- 🎉 Initial release.
1117

18+
[0.2.0]: https://github.com/sunsided/query-string-builder/releases/tag/0.2.0
1219
[0.1.0]: https://github.com/sunsided/query-string-builder/releases/tag/0.1.0

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "query-string-builder"
33
description = "A query string builder for percent encoding key-value pairs"
4-
version = "0.1.0"
4+
version = "0.2.0"
55
edition = "2021"
66
repository = "https://github.com/sunsided/query-string-builder"
77
keywords = ["url", "query-string", "query-argument"]

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ use query_string_builder::QueryString;
1111
fn main() {
1212
let qs = QueryString::new()
1313
.with_value("q", "apple")
14-
.with_value("category", "fruits and vegetables");
14+
.with_opt_value("color", None)
15+
.with_opt_value("category", Some("fruits and vegetables?"));
1516

1617
assert_eq!(
1718
format!("https://example.com/{qs}"),
18-
"https://example.com/?q=apple&category=fruits%20and%20vegetables"
19+
"https://example.com/?q=apple&category=fruits%20and%20vegetables?"
1920
);
2021
}
2122
```

src/lib.rs

Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
//! use query_string_builder::QueryString;
1010
//!
1111
//! let qs = QueryString::new()
12-
//! .with_value("q", "apple")
13-
//! .with_value("category", "fruits and vegetables");
12+
//! .with_value("q", "🍎 apple")
13+
//! .with_opt_value("color", None)
14+
//! .with_opt_value("category", Some("fruits and vegetables?"));
1415
//!
1516
//! assert_eq!(
16-
//! format!("https://example.com/{qs}"),
17-
//! "https://example.com/?q=apple&category=fruits%20and%20vegetables"
17+
//! format!("example.com/{qs}"),
18+
//! "example.com/?q=%F0%9F%8D%8E%20apple&category=fruits%20and%20vegetables?"
1819
//! );
1920
//! ```
2021
@@ -56,17 +57,96 @@ impl<'a> QueryString<'a> {
5657
}
5758

5859
/// Appends a key-value pair to the query string.
60+
///
61+
/// ## Example
62+
///
63+
/// ```
64+
/// use query_string_builder::QueryString;
65+
///
66+
/// let qs = QueryString::new()
67+
/// .with_value("q", "🍎 apple")
68+
/// .with_value("category", "fruits and vegetables");
69+
///
70+
/// assert_eq!(
71+
/// format!("https://example.com/{qs}"),
72+
/// "https://example.com/?q=%F0%9F%8D%8E%20apple&category=fruits%20and%20vegetables"
73+
/// );
74+
/// ```
5975
pub fn with_value(mut self, key: &'a str, value: &'a str) -> Self {
6076
self.pairs.push(Kvp { key, value });
6177
self
6278
}
6379

80+
/// Appends a key-value pair to the query string if the value exists.
81+
///
82+
/// ## Example
83+
///
84+
/// ```
85+
/// use query_string_builder::QueryString;
86+
///
87+
/// let qs = QueryString::new()
88+
/// .with_opt_value("q", Some("🍎 apple"))
89+
/// .with_opt_value("f", None)
90+
/// .with_opt_value("category", Some("fruits and vegetables"));
91+
///
92+
/// assert_eq!(
93+
/// format!("https://example.com/{qs}"),
94+
/// "https://example.com/?q=%F0%9F%8D%8E%20apple&category=fruits%20and%20vegetables"
95+
/// );
96+
/// ```
97+
pub fn with_opt_value(self, key: &'a str, value: Option<&'a str>) -> Self {
98+
if let Some(value) = value {
99+
self.with_value(key, value)
100+
} else {
101+
self
102+
}
103+
}
104+
64105
/// Appends a key-value pair to the query string.
106+
///
107+
/// ## Example
108+
///
109+
/// ```
110+
/// use query_string_builder::QueryString;
111+
///
112+
/// let mut qs = QueryString::new();
113+
/// qs.push("q", "apple");
114+
/// qs.push("category", "fruits and vegetables");
115+
///
116+
/// assert_eq!(
117+
/// format!("https://example.com/{qs}"),
118+
/// "https://example.com/?q=apple&category=fruits%20and%20vegetables"
119+
/// );
120+
/// ```
65121
pub fn push(&mut self, key: &'a str, value: &'a str) -> &Self {
66122
self.pairs.push(Kvp { key, value });
67123
self
68124
}
69125

126+
/// Appends a key-value pair to the query string if the value exists.
127+
///
128+
/// ## Example
129+
///
130+
/// ```
131+
/// use query_string_builder::QueryString;
132+
///
133+
/// let mut qs = QueryString::new();
134+
/// qs.push_opt("q", None);
135+
/// qs.push_opt("q", Some("🍎 apple"));
136+
///
137+
/// assert_eq!(
138+
/// format!("https://example.com/{qs}"),
139+
/// "https://example.com/?q=%F0%9F%8D%8E%20apple"
140+
/// );
141+
/// ```
142+
pub fn push_opt(&mut self, key: &'a str, value: Option<&'a str>) -> &Self {
143+
if let Some(value) = value {
144+
self.push(key, value)
145+
} else {
146+
self
147+
}
148+
}
149+
70150
/// Determines the number of key-value pairs currently in the builder.
71151
pub fn len(&self) -> usize {
72152
self.pairs.len()
@@ -113,11 +193,11 @@ mod tests {
113193
#[test]
114194
fn test_simple() {
115195
let qs = QueryString::new()
116-
.with_value("q", "apple")
196+
.with_value("q", "apple???")
117197
.with_value("category", "fruits and vegetables");
118198
assert_eq!(
119199
qs.to_string(),
120-
"?q=apple&category=fruits%20and%20vegetables"
200+
"?q=apple???&category=fruits%20and%20vegetables"
121201
);
122202
}
123203

@@ -139,4 +219,16 @@ mod tests {
139219
"?q=%F0%9F%A5%A6&%F0%9F%8D%BD%EF%B8%8F=%F0%9F%8D%94%F0%9F%8D%95"
140220
);
141221
}
222+
223+
#[test]
224+
fn test_optional() {
225+
let qs = QueryString::new()
226+
.with_value("q", "celery")
227+
.with_opt_value("taste", None)
228+
.with_opt_value("category", Some("fruits and vegetables"));
229+
assert_eq!(
230+
qs.to_string(),
231+
"?q=celery&category=fruits%20and%20vegetables"
232+
);
233+
}
142234
}

0 commit comments

Comments
 (0)