use core::fmt;
use core::hash::{self, Hasher};
#[cfg(feature = "std")]
use std::{string::String, vec::Vec};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::ExceedsCapacity;
use crate::bitmap::Bitmap;
#[cfg(doc)]
use crate::StrVec28;
#[cfg(doc)]
use crate::StrVec56;
#[cfg(doc)]
use crate::StrVec112;
#[derive(PartialEq, Eq, Copy, Clone)]
pub struct StrVec<T: Bitmap, const N: usize, Alignment> {
pub(crate) bitmap: T,
pub(crate) data: [u8; N],
align: [Alignment; 0],
}
impl<T: Bitmap, const N: usize, Alignment> StrVec<T, N, Alignment> {
#[inline]
pub fn new() -> Self {
Self {
bitmap: T::default(),
data: [0u8; N],
align: [],
}
}
#[track_caller]
pub fn from<S>(values: S) -> Self
where
Self: TryFrom<S>,
<StrVec<T, N, Alignment> as TryFrom<S>>::Error: fmt::Debug,
{
Self::try_from(values).unwrap()
}
#[inline]
pub fn len(&self) -> usize {
self.bitmap.count_ones()
}
#[inline]
pub(crate) fn next_offset(&self) -> usize {
T::BITSIZE - self.bitmap.trailing_zeros()
}
pub fn push(&mut self, s: &str) -> Result<(), ExceedsCapacity> {
let s = if s.is_empty() { "\0" } else { s };
let offset = self.next_offset();
let str_len = s.len();
if offset + str_len > N {
return Err(ExceedsCapacity {
length: offset + str_len,
capacity: N,
});
}
self.bitmap.set(offset + str_len - 1);
self.data[offset..offset + str_len].copy_from_slice(s.as_bytes());
Ok(())
}
pub fn clear(&mut self) {
*self = Self::new();
}
pub fn get(&self, index: usize) -> Option<&str> {
let (offset, end) = self.bitmap.find_nth_span(index)?;
let span = &self.data[offset..end];
if span == [0] {
Some("")
} else {
Some(unsafe { core::str::from_utf8_unchecked(span) })
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn iter(&self) -> impl Iterator<Item = &str> {
let mut offset = 0;
let mut bitmap = self.bitmap;
(0..self.len()).map(move |_| {
let end = bitmap.leading_zeros();
let span = &self.data[offset..(end + 1)];
offset = end + 1;
bitmap.unset(end);
if span == [0] {
""
} else {
unsafe { core::str::from_utf8_unchecked(span) }
}
})
}
#[cfg(feature = "std")]
pub fn to_vec(&self) -> Vec<&str> {
self.iter().collect::<Vec<_>>()
}
}
impl<T: Bitmap, const N: usize, Alignment> Default for StrVec<T, N, Alignment> {
fn default() -> Self {
Self::new()
}
}
impl<T: Bitmap, const N: usize, Alignment> hash::Hash for StrVec<T, N, Alignment> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.data.hash(state);
}
}
impl<T: Bitmap + Eq, const N: usize, Alignment: Eq> Ord for StrVec<T, N, Alignment> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.data.cmp(&other.data)
}
}
impl<T: Bitmap + Eq, const N: usize, Alignment: Eq> PartialOrd for StrVec<T, N, Alignment> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T: Bitmap, const N: usize, Alignment> TryFrom<&[&str]> for StrVec<T, N, Alignment> {
type Error = ExceedsCapacity;
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;
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;
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;
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;
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;
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 {
f.write_str("[")?;
for (i, v) in self.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
write!(f, "{:?}", v)?;
}
f.write_str("]")
}
}
#[cfg(feature = "serde")]
impl<T: Bitmap, const N: usize, Alignment> Serialize for StrVec<T, N, Alignment> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.to_vec().serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T: Bitmap, const N: usize, Alignment> Deserialize<'de> for StrVec<T, N, Alignment> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let v = Vec::<String>::deserialize(deserializer)?;
StrVec::try_from(v).map_err(serde::de::Error::custom)
}
}