Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/bounded_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,20 +240,23 @@ impl<const N: usize, Alignment> fmt::Debug for BoundedStr<N, Alignment> {
}

impl<const N: usize, Alignment> From<&str> for BoundedStr<N, Alignment> {
#[track_caller]
fn from(s: &str) -> Self {
Self::try_from(s).unwrap()
}
}

#[cfg(feature = "std")]
impl<const N: usize, Alignment> From<&String> for BoundedStr<N, Alignment> {
#[track_caller]
fn from(s: &String) -> Self {
Self::try_from(s).unwrap()
}
}

#[cfg(feature = "std")]
impl<const N: usize, Alignment> From<String> for BoundedStr<N, Alignment> {
#[track_caller]
fn from(s: String) -> Self {
Self::try_from(&s).unwrap()
}
Expand Down
3 changes: 3 additions & 0 deletions src/fixed_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,20 +184,23 @@ impl<const N: usize, Alignment> fmt::Debug for FixedStr<N, Alignment> {
}

impl<const N: usize, Alignment> From<&str> for FixedStr<N, Alignment> {
#[track_caller]
fn from(s: &str) -> Self {
Self::try_from(s).unwrap()
}
}

#[cfg(feature = "std")]
impl<const N: usize, Alignment> From<&String> for FixedStr<N, Alignment> {
#[track_caller]
fn from(s: &String) -> Self {
Self::try_from(s).unwrap()
}
}

#[cfg(feature = "std")]
impl<const N: usize, Alignment> From<String> for FixedStr<N, Alignment> {
#[track_caller]
fn from(s: String) -> Self {
Self::try_from(&s).unwrap()
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,5 @@ mod tests {
mod error_tests;
mod fixed_str_tests;
mod str_vec_tests;
mod writer_util;
}
169 changes: 120 additions & 49 deletions src/str_vec.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use core::fmt;
use core::hash::{self, Hasher};

#[cfg(feature = "std")]
use std::fmt;

#[cfg(feature = "std")]
use std::{string::String, vec::Vec};

Expand Down Expand Up @@ -104,56 +102,22 @@ impl<T: Bitmap, const N: usize, Alignment> StrVec<T, N, Alignment> {
}
}

/// Create StrVec from an `&str` iterator
/// Create StrVec from a `&str` or `String` collection, such as:
///
/// # Safety
/// This will panic if StrVec's capacity is exceeded
pub fn from<'a, S>(values: S) -> Self
where
S: IntoIterator<Item = &'a str>,
{
Self::try_from(values).unwrap()
}

/// Attempts to create a StrVec from an `&str` iterator
pub fn try_from<'a, S>(values: S) -> Result<Self, ExceedsCapacity>
where
S: IntoIterator<Item = &'a str>,
{
let mut result = StrVec::<T, N, Alignment>::new();

for v in values {
result.push(v)?;
}

Ok(result)
}

/// Create StrVec from a String iterator
/// - `&[&str]`
/// - `&[String]`
/// - `Vec<&str>`
/// - `Vec<String>`
///
/// # Safety
/// This will panic if StrVec's capacity is exceeded
#[cfg(feature = "std")]
pub fn from_owned<S>(values: S) -> Self
#[track_caller]
pub fn from<S>(values: S) -> Self
where
S: IntoIterator<Item = String>,
Self: TryFrom<S>,
<StrVec<T, N, Alignment> as TryFrom<S>>::Error: fmt::Debug,
{
Self::try_from_owned(values).unwrap()
}

/// Attempts to create a StrVec from an iterator
#[cfg(feature = "std")]
pub fn try_from_owned<S>(values: S) -> Result<Self, ExceedsCapacity>
where
S: IntoIterator<Item = String>,
{
let mut result = Self::new();

for v in values {
result.push(&v)?;
}

Ok(result)
Self::try_from(values).unwrap()
}

/// Number of items in O(1)
Expand Down Expand Up @@ -268,10 +232,117 @@ impl<T: Bitmap + Eq, const N: usize, Alignment: Eq> PartialOrd for StrVec<T, N,
}
}

impl<T: Bitmap, const N: usize, Alignment> TryFrom<&[&str]> for StrVec<T, N, Alignment> {
type Error = ExceedsCapacity;

/// Attempts to create a StrVec from an `&str` slice
fn try_from(values: &[&str]) -> Result<Self, Self::Error> {
let mut result = Self::new();

for v in values {
result.push(v)?;
}

Ok(result)
}
}

impl<T: Bitmap, const N: usize, const I: usize, Alignment> TryFrom<[&str; I]>
for StrVec<T, N, Alignment>
{
type Error = ExceedsCapacity;

/// Attempts to create a StrVec from an `&str` array
fn try_from(values: [&str; I]) -> Result<Self, Self::Error> {
let mut result = Self::new();

for v in values {
result.push(v)?;
}

Ok(result)
}
}

#[cfg(feature = "std")]
impl<T: Bitmap, const N: usize, Alignment> TryFrom<Vec<&str>> for StrVec<T, N, Alignment> {
type Error = ExceedsCapacity;

/// Attempts to create a StrVec from an `&str` vector
fn try_from(values: Vec<&str>) -> Result<Self, Self::Error> {
let mut result = Self::new();

for v in values {
result.push(v)?;
}

Ok(result)
}
}

#[cfg(feature = "std")]
impl<T: Bitmap, const N: usize, Alignment> TryFrom<&[String]> for StrVec<T, N, Alignment> {
type Error = ExceedsCapacity;

/// Attempts to create a StrVec from a `String` slice
fn try_from(values: &[String]) -> Result<Self, Self::Error> {
let mut result = Self::new();

for v in values {
result.push(v)?;
}

Ok(result)
}
}

#[cfg(feature = "std")]
impl<T: Bitmap, const N: usize, const I: usize, Alignment> TryFrom<[String; I]>
for StrVec<T, N, Alignment>
{
type Error = ExceedsCapacity;

/// Attempts to create a StrVec from a `String` array
fn try_from(values: [String; I]) -> Result<Self, Self::Error> {
let mut result = Self::new();

for v in values {
result.push(&v)?;
}

Ok(result)
}
}

#[cfg(feature = "std")]
impl<T: Bitmap, const N: usize, Alignment> TryFrom<Vec<String>> for StrVec<T, N, Alignment> {
type Error = ExceedsCapacity;

/// Attempts to create a StrVec from a `String` vector
fn try_from(values: Vec<String>) -> Result<Self, Self::Error> {
let mut result = Self::new();

for v in values {
result.push(&v)?;
}

Ok(result)
}
}

impl<T: Bitmap, const N: usize, Alignment> fmt::Debug for StrVec<T, N, Alignment> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.to_vec().fmt(f)
f.write_str("[")?;

for (i, v) in self.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}

write!(f, "{:?}", v)?;
}

f.write_str("]")
}
}

Expand All @@ -292,6 +363,6 @@ impl<'de, T: Bitmap, const N: usize, Alignment> Deserialize<'de> for StrVec<T, N
D: serde::Deserializer<'de>,
{
let v = Vec::<String>::deserialize(deserializer)?;
StrVec::try_from_owned(v).map_err(serde::de::Error::custom)
StrVec::try_from(v).map_err(serde::de::Error::custom)
}
}
79 changes: 74 additions & 5 deletions src/tests/str_vec_tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#![allow(clippy::unusual_byte_groupings)]

use core::fmt::Write;
use core::mem;

use crate::{ExceedsCapacity, StrVec, StrVec28, StrVec56, StrVec112, alignment::Align16};
use crate::{
ExceedsCapacity, StrVec, StrVec28, StrVec56, StrVec112, alignment::Align16,
tests::writer_util::ByteMutWriter,
};

#[test]
fn test_size() {
Expand Down Expand Up @@ -173,14 +178,25 @@ fn test_next_offset() {
assert_eq!(v.next_offset(), 1 + 2 + 3);
}

#[test]
fn test_debug() {
let v = StrVec28::try_from(["a", "b", "c"]).unwrap();

let mut buf = [0u8; 20];
let mut buf = ByteMutWriter::new(&mut buf[..]);
write!(&mut buf, "{:?}", v).unwrap();

assert_eq!(buf.as_str(), r#"["a", "b", "c"]"#);
}

#[cfg(feature = "std")]
mod std {
use std::collections::HashSet;
use std::format;
use std::vec;
use std::{collections::BTreeSet, vec::Vec};

use crate::{StrVec28, StrVec56, StrVec112};
use crate::{StrVec56, StrVec112};

#[test]
fn test_hash() {
Expand All @@ -198,6 +214,30 @@ mod std {
assert_eq!(set.len(), 2);
}

#[test]
fn test_from_slice() {
let arr: &[&str] = &["a", "b"];
let vec = StrVec56::from(arr);

assert_eq!(vec.iter().collect::<Vec<_>>(), vec!["a", "b"]);
}

#[test]
fn test_try_from_slice() {
let arr: &[&str] = &["a", "b"];
let vec = StrVec56::try_from(arr).unwrap();

assert_eq!(vec.iter().collect::<Vec<_>>(), vec!["a", "b"]);
}

#[test]
fn test_try_from_vec() {
let arr: Vec<&str> = vec!["a", "b"];
let vec = StrVec56::try_from(arr).unwrap();

assert_eq!(vec.iter().collect::<Vec<_>>(), vec!["a", "b"]);
}

#[test]
fn test_ord() {
let s1 = StrVec112::try_from(["ab", "a1"]).unwrap();
Expand Down Expand Up @@ -248,11 +288,40 @@ mod std {
assert_eq!(collected.len(), 56);
assert_eq!(collected, insert);
}
}

#[cfg(feature = "std")]
mod std_tests {
use std::{
string::{String, ToString},
vec,
vec::Vec,
};

use crate::StrVec56;

#[test]
fn test_from_slice() {
let arr: &[String] = &["a".to_string(), "b".to_string()];
let vec = StrVec56::from(arr);

assert_eq!(vec.iter().collect::<Vec<_>>(), vec!["a", "b"]);
}

#[test]
fn test_try_from_slice() {
let arr: &[String] = &["a".to_string(), "b".to_string()];
let vec = StrVec56::try_from(arr).unwrap();

assert_eq!(vec.iter().collect::<Vec<_>>(), vec!["a", "b"]);
}

#[test]
fn test_debug() {
let v = StrVec28::try_from(["a", "b", "c"]).unwrap();
assert_eq!(format!("{:?}", v), r#"["a", "b", "c"]"#);
fn test_try_from_vec() {
let arr: Vec<String> = vec!["a".to_string(), "b".to_string()];
let vec = StrVec56::try_from(arr).unwrap();

assert_eq!(vec.iter().collect::<Vec<_>>(), vec!["a", "b"]);
}
}

Expand Down
Loading
Loading