Skip to content

Commit bdc3db2

Browse files
committed
v0.3.1
- add `join` method
1 parent 392af2f commit bdc3db2

File tree

5 files changed

+67
-5
lines changed

5 files changed

+67
-5
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
authors = ["Davide Di Carlo <[email protected]>"]
33
description = "Extension traits for `String` and `&str` types."
44
name = "string_more"
5-
version = "0.3.0"
5+
version = "0.3.1"
66
edition = "2021"
77
license = "MIT"
88
keywords = ["String", "str", "extension", "in-place", "edit-distance"]

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2024 Davide Di Carlo
3+
Copyright (c) 2025 Davide Di Carlo
44

55
Permission is hereby granted, free of charge, to any person
66
obtaining a copy of this software and associated documentation

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,13 @@ let s = "🦀";
229229
s.previous_char_boundary(2); // 0
230230
```
231231

232+
- **`join`**: Joins an iterator of items into a single `String`.
233+
234+
```rust
235+
let result = ", ".join(["one", "two", "three"]);
236+
assert_eq!(result, "one, two, three");
237+
```
238+
232239
## Safety and Coverage
233240

234241
This crate contains a small portion of unsafe code.

src/lib.rs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! - **Flexible and Efficient**: Designed to extend the standard string functionality without sacrificing performance.
1212
1313
use std::collections::{BTreeMap, HashMap};
14+
use std::fmt::{Display, Write};
1415
use std::ops::Deref;
1516

1617
mod sailed {
@@ -131,6 +132,14 @@ pub trait StrExt: sailed::Sailed {
131132
/// If index happens to be on a valid char boundary then index itself is returned.
132133
/// Note that both 0 and string's length are consedered valid char boundaries.
133134
fn previous_char_boundary(&self, index: usize) -> usize;
135+
136+
/// Joins an iterator of items into a single `String`, using `self` as the separator.
137+
///
138+
/// Each item is formatted using the `Display` trait and concatenated with `self`
139+
/// placed between consecutive items.
140+
fn join<T: Display>(&self, iterable: impl IntoIterator<Item = T>) -> String
141+
where
142+
Self: Display;
134143
}
135144

136145
/// The `StringExt` trait extends `String` with advanced in-place manipulation methods,
@@ -194,9 +203,9 @@ pub trait StringExt: StrExt {
194203
fn replace_in_place(&mut self, from: impl EncodeUtf8, to: impl EncodeUtf8);
195204
}
196205

197-
impl<T> StrExt for T
206+
impl<S> StrExt for S
198207
where
199-
T: sailed::Sailed + Deref<Target = str>,
208+
S: sailed::Sailed + Deref<Target = str>,
200209
{
201210
fn fill_start(&self, fill: impl EncodeUtf8, times: usize) -> String {
202211
let mut buf = Default::default();
@@ -476,6 +485,22 @@ where
476485

477486
index
478487
}
488+
489+
fn join<T: Display>(&self, iterable: impl IntoIterator<Item = T>) -> String
490+
where
491+
Self: Display,
492+
{
493+
let mut iter = iterable.into_iter();
494+
let mut acc = String::new();
495+
496+
if let Some(value) = iter.next() {
497+
write!(acc, "{value}").unwrap();
498+
iter.try_for_each(|item| write!(acc, "{self}{item}"))
499+
.unwrap();
500+
}
501+
502+
acc
503+
}
479504
}
480505

481506
impl StringExt for String {
@@ -1380,4 +1405,34 @@ mod tests {
13801405
assert_eq!(sut.longest_common_substring(other), expected);
13811406
}
13821407
}
1408+
1409+
#[test]
1410+
fn join_strings() {
1411+
let result = ", ".join(["one", "two", "three"]);
1412+
assert_eq!(result, "one, two, three");
1413+
}
1414+
1415+
#[test]
1416+
fn join_integers() {
1417+
let result = "-".join([1, 2, 3, 4]);
1418+
assert_eq!(result, "1-2-3-4");
1419+
}
1420+
1421+
#[test]
1422+
fn join_single_item() {
1423+
let result = "/".join(["only"]);
1424+
assert_eq!(result, "only");
1425+
}
1426+
1427+
#[test]
1428+
fn join_empty_iterator() {
1429+
let result = ";".join(std::iter::empty::<String>());
1430+
assert_eq!(result, "");
1431+
}
1432+
1433+
#[test]
1434+
fn join_non_ascii_strings() {
1435+
let result = "·".join(["Ā", "❤️", "Ȁ"]);
1436+
assert_eq!(result, "Ā·❤️·Ȁ");
1437+
}
13831438
}

0 commit comments

Comments
 (0)