Somthing is wrong with `SmallString<SIZE>`, look into it (From<&str> fails, always.)

Fortune for stack-str's current commit: Small blessing − 小吉
master
Avril 2 years ago
parent e7cee15f4c
commit 75de2567a8
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -262,6 +262,7 @@ impl<const SIZE: usize> std::str::FromStr for StackString<SIZE>
}
}
}
impl<const SIZE: usize> TryFrom<String> for StackString<SIZE>
{
type Error = StrTooLargeError<SIZE>;
@ -273,6 +274,19 @@ impl<const SIZE: usize> TryFrom<String> for StackString<SIZE>
}
}
impl<'a, const SIZE: usize> TryFrom<&'a str> for StackString<SIZE>
{
type Error = StrTooLargeError<SIZE>;
#[inline]
fn try_from(from: &'a str) -> Result<Self, Self::Error>
{
from.parse()
}
}
impl<const SIZE: usize> TryFrom<[u8; SIZE]> for StackString<SIZE>
{
type Error = std::str::Utf8Error;

@ -138,7 +138,7 @@ impl HeapString {
impl From<HeapString> for String
{
#[inline]
#[inline(always)]
fn from(from: HeapString) -> Self
{
from.into_boxed_str().into()
@ -148,13 +148,51 @@ impl From<HeapString> for String
impl From<String> for HeapString
{
#[inline]
#[inline(always)]
fn from(from: String) -> Self
{
Self::new(from.into_boxed_str())
}
}
impl From<Box<str>> for HeapString
{
#[inline(always)]
fn from(from: Box<str>) -> Self
{
Self::new(from)
}
}
impl From<HeapString> for Box<str>
{
#[inline(always)]
fn from(from: HeapString) -> Self
{
from.into_boxed_str()
}
}
impl From<HeapString> for Box<[u8]>
{
#[inline(always)]
fn from(from: HeapString) -> Self
{
from.into_boxed_bytes()
}
}
impl<'a> From<&'a str> for HeapString
{
#[inline(always)]
fn from(from: &'a str) -> Self
{
Self::new(from.into())
}
}
impl ops::Drop for HeapString
{
@ -396,6 +434,69 @@ impl<const SIZE: usize> ops::Deref for SmallString<SIZE>
}
}
impl<'a, const SIZE: usize> From<&'a str> for SmallString<SIZE>
{
#[inline]
fn from(string: &'a str) -> Self {
if string.len() <= SIZE {
match StackString::<SIZE>::try_from(string) {
Ok(ss) => return ss.into(),
_ => (),
}
}
// Too large, shunt to heap
HeapString::from(string).into()
}
}
impl<const SIZE: usize> From<StackString<SIZE>> for SmallString<SIZE>
{
#[inline]
fn from(from: StackString<SIZE>) -> Self
{
Self {
inner: SmallStringInner {
stack: ManuallyDrop::new(from),
}
}
}
}
impl<const SIZE: usize> From<HeapString> for SmallString<SIZE>
{
#[inline(always)]
fn from(from: HeapString) -> Self
{
Self {
inner: SmallStringInner {
heap: ManuallyDrop::new(from),
}
}
}
}
impl<const SIZE: usize> From<SmallString<SIZE>> for HeapString
{
#[inline(always)]
fn from(mut from: SmallString<SIZE>) -> Self
{
let h = if from.is_allocated() {
unsafe {
ManuallyDrop::take(&mut from.inner.heap)
}
} else {
unsafe {
from.inner.stack.as_str()
}.into()
};
std::mem::forget(from);
h
}
}
impl<const SIZE: usize> From<String> for SmallString<SIZE>
{
#[inline]
@ -497,8 +598,8 @@ impl<const SIZE: usize> fmt::Write for SmallString<SIZE>
let mut buf = [0u8; mem::size_of::<char>()];
unsafe { self.shunt_to_heap_with_unchecked(
std::iter::once_with(|| c.encode_utf8(&mut buf[..])).map(|&mut ref x| x)
);
std::iter::once_with(|| c.encode_utf8(&mut buf[..])).map(|&mut ref x| x)
);
}
} else {
// Room in stack for `c`
@ -511,4 +612,39 @@ impl<const SIZE: usize> fmt::Write for SmallString<SIZE>
}
}
//TODO: SmallString: io::Write impls when extending functions have been written
const _:() = {
use std::io::{
self,
Write,
};
impl<const SIZE: usize> Write for SmallString<SIZE>
{
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let buf = std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
Ok(self.extend_from_str(buf).len())
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
let buf = std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
(self.extend_from_str(buf).len() == buf.len())
.then(|| ()).ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "failed to write entire buffer"))
}
}
};
#[cfg(test)]
mod tests
{
use super::*;
#[test]
fn extending()
{
let mut ss: SmallString<40> = "Hello world".into();
}
}

Loading…
Cancel
Save