Skip to content

Commit c053490

Browse files
String: make string generic over the storage, like Vec
1 parent 400732b commit c053490

File tree

2 files changed

+45
-30
lines changed

2 files changed

+45
-30
lines changed

src/ser.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use core::hash::{BuildHasher, Hash};
22

33
use crate::{
4-
binary_heap::Kind as BinaryHeapKind, BinaryHeap, Deque, IndexMap, IndexSet, LinearMap, String,
5-
Vec,
4+
binary_heap::Kind as BinaryHeapKind, storage::Storage, string::StringInner, BinaryHeap, Deque,
5+
IndexMap, IndexSet, LinearMap, Vec,
66
};
77
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
88

@@ -113,10 +113,10 @@ where
113113

114114
// String containers
115115

116-
impl<const N: usize> Serialize for String<N> {
117-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
116+
impl<S: Storage> Serialize for StringInner<S> {
117+
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
118118
where
119-
S: Serializer,
119+
SER: Serializer,
120120
{
121121
serializer.serialize_str(&*self)
122122
}

src/string.rs

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ use core::{
99
str::{self, Utf8Error},
1010
};
1111

12-
use crate::Vec;
12+
use crate::{
13+
storage::{OwnedStorage, Storage, ViewStorage},
14+
vec::VecInner,
15+
Vec,
16+
};
1317

1418
/// A possible error value when converting a [`String`] from a UTF-16 byte slice.
1519
///
@@ -33,11 +37,20 @@ impl fmt::Display for FromUtf16Error {
3337
}
3438
}
3539

36-
/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
37-
pub struct String<const N: usize> {
38-
vec: Vec<u8, N>,
40+
/// Base struct for [`String`] and [`StringView`], generic over the [`Storage`].
41+
///
42+
/// In most cases you should use [`String`] or [`StringView`] directly. Only use this
43+
/// struct if you want to write code that's generic over both.
44+
pub struct StringInner<S: Storage> {
45+
vec: VecInner<u8, S>,
3946
}
4047

48+
/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
49+
pub type String<const N: usize> = StringInner<OwnedStorage<N>>;
50+
51+
/// A dynamic capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
52+
pub type StringView = StringInner<ViewStorage>;
53+
4154
impl<const N: usize> String<N> {
4255
/// Constructs a new, empty `String` with a fixed capacity of `N` bytes.
4356
///
@@ -180,7 +193,9 @@ impl<const N: usize> String<N> {
180193
pub fn into_bytes(self) -> Vec<u8, N> {
181194
self.vec
182195
}
196+
}
183197

198+
impl<S: Storage> StringInner<S> {
184199
/// Extracts a string slice containing the entire string.
185200
///
186201
/// # Examples
@@ -248,7 +263,7 @@ impl<const N: usize> String<N> {
248263
/// assert_eq!(s, "olleh");
249264
/// # Ok::<(), ()>(())
250265
/// ```
251-
pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8, N> {
266+
pub unsafe fn as_mut_vec(&mut self) -> &mut VecInner<u8, S> {
252267
&mut self.vec
253268
}
254269

@@ -521,26 +536,26 @@ impl<const N: usize> Clone for String<N> {
521536
}
522537
}
523538

524-
impl<const N: usize> fmt::Debug for String<N> {
539+
impl<S: Storage> fmt::Debug for StringInner<S> {
525540
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526541
<str as fmt::Debug>::fmt(self, f)
527542
}
528543
}
529544

530-
impl<const N: usize> fmt::Display for String<N> {
545+
impl<S: Storage> fmt::Display for StringInner<S> {
531546
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532547
<str as fmt::Display>::fmt(self, f)
533548
}
534549
}
535550

536-
impl<const N: usize> hash::Hash for String<N> {
551+
impl<S: Storage> hash::Hash for StringInner<S> {
537552
#[inline]
538553
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
539554
<str as hash::Hash>::hash(self, hasher)
540555
}
541556
}
542557

543-
impl<const N: usize> fmt::Write for String<N> {
558+
impl<S: Storage> fmt::Write for StringInner<S> {
544559
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
545560
self.push_str(s).map_err(|_| fmt::Error)
546561
}
@@ -550,82 +565,82 @@ impl<const N: usize> fmt::Write for String<N> {
550565
}
551566
}
552567

553-
impl<const N: usize> ops::Deref for String<N> {
568+
impl<S: Storage> ops::Deref for StringInner<S> {
554569
type Target = str;
555570

556571
fn deref(&self) -> &str {
557572
self.as_str()
558573
}
559574
}
560575

561-
impl<const N: usize> ops::DerefMut for String<N> {
576+
impl<S: Storage> ops::DerefMut for StringInner<S> {
562577
fn deref_mut(&mut self) -> &mut str {
563578
self.as_mut_str()
564579
}
565580
}
566581

567-
impl<const N: usize> AsRef<str> for String<N> {
582+
impl<S: Storage> AsRef<str> for StringInner<S> {
568583
#[inline]
569584
fn as_ref(&self) -> &str {
570585
self
571586
}
572587
}
573588

574-
impl<const N: usize> AsRef<[u8]> for String<N> {
589+
impl<S: Storage> AsRef<[u8]> for StringInner<S> {
575590
#[inline]
576591
fn as_ref(&self) -> &[u8] {
577592
self.as_bytes()
578593
}
579594
}
580595

581-
impl<const N1: usize, const N2: usize> PartialEq<String<N2>> for String<N1> {
582-
fn eq(&self, rhs: &String<N2>) -> bool {
596+
impl<S1: Storage, S2: Storage> PartialEq<StringInner<S1>> for StringInner<S2> {
597+
fn eq(&self, rhs: &StringInner<S1>) -> bool {
583598
str::eq(&**self, &**rhs)
584599
}
585600
}
586601

587602
// String<N> == str
588-
impl<const N: usize> PartialEq<str> for String<N> {
603+
impl<S: Storage> PartialEq<str> for StringInner<S> {
589604
#[inline]
590605
fn eq(&self, other: &str) -> bool {
591606
str::eq(self, other)
592607
}
593608
}
594609

595610
// String<N> == &'str
596-
impl<const N: usize> PartialEq<&str> for String<N> {
611+
impl<S: Storage> PartialEq<&str> for StringInner<S> {
597612
#[inline]
598613
fn eq(&self, other: &&str) -> bool {
599614
str::eq(self, &other[..])
600615
}
601616
}
602617

603618
// str == String<N>
604-
impl<const N: usize> PartialEq<String<N>> for str {
619+
impl<S: Storage> PartialEq<StringInner<S>> for str {
605620
#[inline]
606-
fn eq(&self, other: &String<N>) -> bool {
621+
fn eq(&self, other: &StringInner<S>) -> bool {
607622
str::eq(self, &other[..])
608623
}
609624
}
610625

611626
// &'str == String<N>
612-
impl<const N: usize> PartialEq<String<N>> for &str {
627+
impl<S: Storage> PartialEq<StringInner<S>> for &str {
613628
#[inline]
614-
fn eq(&self, other: &String<N>) -> bool {
629+
fn eq(&self, other: &StringInner<S>) -> bool {
615630
str::eq(self, &other[..])
616631
}
617632
}
618633

619-
impl<const N: usize> Eq for String<N> {}
634+
impl<S: Storage> Eq for StringInner<S> {}
620635

621-
impl<const N1: usize, const N2: usize> PartialOrd<String<N2>> for String<N1> {
636+
impl<S1: Storage, S2: Storage> PartialOrd<StringInner<S1>> for StringInner<S2> {
622637
#[inline]
623-
fn partial_cmp(&self, other: &String<N2>) -> Option<Ordering> {
638+
fn partial_cmp(&self, other: &StringInner<S1>) -> Option<Ordering> {
624639
PartialOrd::partial_cmp(&**self, &**other)
625640
}
626641
}
627642

628-
impl<const N: usize> Ord for String<N> {
643+
impl<S: Storage> Ord for StringInner<S> {
629644
#[inline]
630645
fn cmp(&self, other: &Self) -> Ordering {
631646
Ord::cmp(&**self, &**other)

0 commit comments

Comments
 (0)