no_std support
This commit is contained in:
1 parent
78b940ff19
commit
0b4dbc6bc5
12 files changed
+150
-55
No files matched your search
@@ -3,5 +3,10 @@ name = "libshire"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std", "serde"]
|
||||||
|
alloc = ["serde?/alloc"]
|
||||||
|
std = ["serde?/std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1", default-features = false, optional = true }
|
serde = { version = "1", default-features = false, optional = true }
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
use std::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
|
||||||
/// Consumes an element of type `Infallible` and produces an element of any type `T`. This is
|
/// Consumes an element of type `Infallible` and produces an element of any type `T`. This is
|
||||||
/// possible because `Infallible` has no elements and thus this function can never be called, so
|
/// possible because `Infallible` has no elements and thus this function can never be called, so
|
||||||
|
|||||||
+7
-7
@@ -1,9 +1,8 @@
|
|||||||
use std::{
|
use core::{
|
||||||
convert::identity,
|
convert::identity,
|
||||||
fmt,
|
fmt,
|
||||||
hint,
|
hint,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
process::{ExitCode, Termination},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::convert::{clone, clone_mut, copy, copy_mut, Empty};
|
use crate::convert::{clone, clone_mut, copy, copy_mut, Empty};
|
||||||
@@ -586,14 +585,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> Termination for Either<L, R>
|
#[cfg(feature = "std")]
|
||||||
|
impl<L, R> std::process::Termination for Either<L, R>
|
||||||
where
|
where
|
||||||
L: Termination,
|
L: std::process::Termination,
|
||||||
R: Termination,
|
R: std::process::Termination,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn report(self) -> ExitCode {
|
fn report(self) -> std::process::ExitCode {
|
||||||
self.fold(<L as Termination>::report, <R as Termination>::report)
|
self.fold(<L as std::process::Termination>::report, <R as std::process::Termination>::report)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-4
@@ -1,5 +1,4 @@
|
|||||||
use std::{
|
use core::{
|
||||||
error,
|
|
||||||
fmt::{self, Write},
|
fmt::{self, Write},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
@@ -215,7 +214,8 @@ impl fmt::Display for ParseError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for ParseError {}
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for ParseError {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ArrayParseError {
|
pub enum ArrayParseError {
|
||||||
@@ -232,7 +232,8 @@ impl fmt::Display for ArrayParseError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for ArrayParseError {}
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for ArrayParseError {}
|
||||||
|
|
||||||
impl From<ParseError> for ArrayParseError {
|
impl From<ParseError> for ArrayParseError {
|
||||||
fn from(err: ParseError) -> Self {
|
fn from(err: ParseError) -> Self {
|
||||||
@@ -244,8 +245,12 @@ impl From<ParseError> for ArrayParseError {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hex_bytes_debug() {
|
fn test_hex_bytes_debug() {
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::format;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{:?}", HexBytes::<Lowercase>::new(&[0x87, 0xe1, 0x8f, 0xaa, 0x88, 0x8d, 0x43, 0x4e, 0xf2, 0xb2, 0x5d, 0xe1, 0xa5, 0x1b, 0xa0, 0x94])),
|
format!("{:?}", HexBytes::<Lowercase>::new(&[0x87, 0xe1, 0x8f, 0xaa, 0x88, 0x8d, 0x43, 0x4e, 0xf2, 0xb2, 0x5d, 0xe1, 0xa5, 0x1b, 0xa0, 0x94])),
|
||||||
"[0x87, 0xe1, 0x8f, 0xaa, 0x88, 0x8d, 0x43, 0x4e, 0xf2, 0xb2, 0x5d, 0xe1, 0xa5, 0x1b, 0xa0, 0x94]"
|
"[0x87, 0xe1, 0x8f, 0xaa, 0x88, 0x8d, 0x43, 0x4e, 0xf2, 0xb2, 0x5d, 0xe1, 0xa5, 0x1b, 0xa0, 0x94]"
|
||||||
@@ -257,8 +262,12 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hex_bytes_display() {
|
fn test_hex_bytes_display() {
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::string::ToString;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
HexBytes::<Lowercase>::new(&[0x87, 0xe1, 0x8f, 0xaa, 0x88, 0x8d, 0x43, 0x4e, 0xf2, 0xb2, 0x5d, 0xe1, 0xa5, 0x1b, 0xa0, 0x94]).to_string(),
|
HexBytes::<Lowercase>::new(&[0x87, 0xe1, 0x8f, 0xaa, 0x88, 0x8d, 0x43, 0x4e, 0xf2, 0xb2, 0x5d, 0xe1, 0xa5, 0x1b, 0xa0, 0x94]).to_string(),
|
||||||
"87e18faa888d434ef2b25de1a51ba094"
|
"87e18faa888d434ef2b25de1a51ba094"
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod convert;
|
pub mod convert;
|
||||||
pub mod either;
|
pub mod either;
|
||||||
pub mod hex;
|
pub mod hex;
|
||||||
|
|||||||
+31
-8
@@ -1,13 +1,25 @@
|
|||||||
use std::{
|
use core::{
|
||||||
borrow::{self, Cow},
|
borrow,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
error,
|
|
||||||
fmt,
|
fmt,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
ops,
|
ops,
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::{
|
||||||
|
borrow::{Cow, ToOwned},
|
||||||
|
boxed::Box,
|
||||||
|
string::String,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CappedString<const N: usize> {
|
pub struct CappedString<const N: usize> {
|
||||||
buf: [u8; N],
|
buf: [u8; N],
|
||||||
@@ -97,10 +109,6 @@ impl<const N: usize> CappedString<N> {
|
|||||||
unsafe { str::from_utf8_unchecked_mut(slice) }
|
unsafe { str::from_utf8_unchecked_mut(slice) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_string(self) -> String {
|
|
||||||
self.as_str().to_owned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
usize::from(self.len)
|
usize::from(self.len)
|
||||||
}
|
}
|
||||||
@@ -110,6 +118,17 @@ impl<const N: usize> CappedString<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
|
impl<const N: usize> CappedString<N> {
|
||||||
|
pub fn into_boxed_str(self) -> Box<str> {
|
||||||
|
self.as_str().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_string(self) -> String {
|
||||||
|
self.as_str().to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<const N: usize> Default for CappedString<N> {
|
impl<const N: usize> Default for CappedString<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@@ -170,6 +189,7 @@ impl<'a, const N: usize> TryFrom<&'a str> for CappedString<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
impl<const N: usize> TryFrom<String> for CappedString<N> {
|
impl<const N: usize> TryFrom<String> for CappedString<N> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@@ -179,6 +199,7 @@ impl<const N: usize> TryFrom<String> for CappedString<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
impl<'a, const N: usize> TryFrom<Cow<'a, str>> for CappedString<N> {
|
impl<'a, const N: usize> TryFrom<Cow<'a, str>> for CappedString<N> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@@ -188,6 +209,7 @@ impl<'a, const N: usize> TryFrom<Cow<'a, str>> for CappedString<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
impl<const N: usize> From<CappedString<N>> for String {
|
impl<const N: usize> From<CappedString<N>> for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(s: CappedString<N>) -> Self {
|
fn from(s: CappedString<N>) -> Self {
|
||||||
@@ -275,4 +297,5 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for Error {}
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for Error {}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use core::{
|
||||||
borrow::{self, Cow},
|
borrow,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
fmt,
|
fmt,
|
||||||
@@ -12,6 +12,16 @@ use std::{
|
|||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::{
|
||||||
|
borrow::Cow,
|
||||||
|
boxed::Box,
|
||||||
|
string::String,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
/// A non-growable string where strings 23 bytes or shorter are stored inline and longer strings
|
/// A non-growable string where strings 23 bytes or shorter are stored inline and longer strings
|
||||||
/// use a separate heap allocation. If maximum inline lengths other than 23 are desired, see the
|
/// use a separate heap allocation. If maximum inline lengths other than 23 are desired, see the
|
||||||
/// more general [InliningString].
|
/// more general [InliningString].
|
||||||
@@ -274,7 +284,7 @@ impl<const N: usize> InliningString<N> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn into_string(self) -> String {
|
pub fn into_boxed_str(self) -> Box<str> {
|
||||||
match self.inline_string_len() {
|
match self.inline_string_len() {
|
||||||
Some(len) => {
|
Some(len) => {
|
||||||
// Get a pointer to the `inline` field of the union.
|
// Get a pointer to the `inline` field of the union.
|
||||||
@@ -296,7 +306,7 @@ impl<const N: usize> InliningString<N> {
|
|||||||
// of `InliningString`.
|
// of `InliningString`.
|
||||||
let str_slice = unsafe { str::from_utf8_unchecked(bytes) };
|
let str_slice = unsafe { str::from_utf8_unchecked(bytes) };
|
||||||
|
|
||||||
str_slice.to_owned()
|
Box::from(str_slice)
|
||||||
},
|
},
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
@@ -328,13 +338,18 @@ impl<const N: usize> InliningString<N> {
|
|||||||
// The boxed string is initialised, as we obtained it by moving `repr.boxed`, and
|
// The boxed string is initialised, as we obtained it by moving `repr.boxed`, and
|
||||||
// the only time `repr.boxed` is uninitialised is when it is briefly replaced with
|
// the only time `repr.boxed` is uninitialised is when it is briefly replaced with
|
||||||
// a temporary value in the block above.
|
// a temporary value in the block above.
|
||||||
let box_str = unsafe { maybe_box_str.assume_init() };
|
unsafe { maybe_box_str.assume_init() }
|
||||||
|
|
||||||
box_str.into_string()
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub fn into_string(self) -> String {
|
||||||
|
self.into_boxed_str()
|
||||||
|
.into_string()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn heap_allocated(&self) -> bool {
|
pub fn heap_allocated(&self) -> bool {
|
||||||
@@ -519,19 +534,26 @@ impl<'de, const N: usize> serde::Deserialize<'de> for InliningString<N> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::{
|
||||||
|
borrow::{Cow, ToOwned},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_align() {
|
fn test_align() {
|
||||||
use std::mem::align_of;
|
use core::mem::align_of;
|
||||||
assert_eq!(align_of::<InliningString23>(), align_of::<Box<str>>());
|
assert_eq!(align_of::<InliningString23>(), align_of::<Box<str>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_niche() {
|
fn test_niche() {
|
||||||
use std::mem::size_of;
|
use core::mem::size_of;
|
||||||
assert_eq!(size_of::<InliningString23>(), size_of::<Option<InliningString23>>());
|
assert_eq!(size_of::<InliningString23>(), size_of::<Option<InliningString23>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::{
|
use core::{
|
||||||
borrow,
|
borrow,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
error,
|
|
||||||
fmt,
|
fmt,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
ops,
|
ops,
|
||||||
@@ -191,7 +190,8 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for Error {}
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
+38
-20
@@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use core::{
|
||||||
borrow::{self, Cow},
|
borrow,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
fmt,
|
fmt,
|
||||||
@@ -8,12 +8,18 @@ use std::{
|
|||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::{borrow::Cow, boxed::Box, string::String};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use super::CappedString;
|
use super::CappedString;
|
||||||
|
|
||||||
/// A non-growable string where strings 22 bytes or shorter are stored inline and longer strings
|
/// A non-growable string where strings 22 bytes or shorter are stored inline and longer strings
|
||||||
/// use a separate heap allocation. If maximum inline lengths other than 22 are desired, see the
|
/// use a separate heap allocation. If maximum inline lengths other than 22 are desired, see the
|
||||||
/// more general [InliningString].
|
/// more general [InliningString].
|
||||||
///
|
///
|
||||||
/// 22 bytes is chosen because it is optimal for 64-bit architectures; the minimum possible size
|
/// 22 bytes is chosen because it is optimal for 64-bit architectures; the minimum possible size
|
||||||
/// of the data structure on 64-bit architectures which always keeps the data properly aligned is
|
/// of the data structure on 64-bit architectures which always keeps the data properly aligned is
|
||||||
/// 24 bytes (because, when heap-allocated, the data structure contains a 16-byte `Box<[u8]>` with
|
/// 24 bytes (because, when heap-allocated, the data structure contains a 16-byte `Box<[u8]>` with
|
||||||
@@ -24,23 +30,23 @@ pub type InliningString22 = InliningString<22>;
|
|||||||
/// A non-growable string which stores small strings inline; strings of length less than or equal
|
/// A non-growable string which stores small strings inline; strings of length less than or equal
|
||||||
/// to `N` are stored inside the data structure itself, whereas strings of length greater than `N`
|
/// to `N` are stored inside the data structure itself, whereas strings of length greater than `N`
|
||||||
/// use a separate heap allocation.
|
/// use a separate heap allocation.
|
||||||
///
|
///
|
||||||
/// This type is intended to be used when lots of small strings need to be stored, and these
|
/// This type is intended to be used when lots of small strings need to be stored, and these
|
||||||
/// strings do not need to grow.
|
/// strings do not need to grow.
|
||||||
///
|
///
|
||||||
/// For 64-bit targets, `N = 22` allows the greatest amount of inline string data to be stored
|
/// For 64-bit targets, `N = 22` allows the greatest amount of inline string data to be stored
|
||||||
/// without exceeding the size of a regular [String]. Therefore, [InliningString22] is provided as
|
/// without exceeding the size of a regular [String]. Therefore, [InliningString22] is provided as
|
||||||
/// a type alias for `InliningString<22>`.
|
/// a type alias for `InliningString<22>`.
|
||||||
///
|
///
|
||||||
/// Although `N` is a `usize`, it may be no greater than `u8::MAX`; larger values will result in a
|
/// Although `N` is a `usize`, it may be no greater than `u8::MAX`; larger values will result in a
|
||||||
/// compile-time error.
|
/// compile-time error.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use libshire::strings::InliningString;
|
/// # use libshire::strings::InliningString;
|
||||||
/// let s1 = InliningString::<22>::new("Hello, InliningString!");
|
/// let s1 = InliningString::<22>::new("Hello, InliningString!");
|
||||||
/// assert_eq!(&*s1, "Hello, InliningString!");
|
/// assert_eq!(&*s1, "Hello, InliningString!");
|
||||||
/// assert!(!s1.heap_allocated());
|
/// assert!(!s1.heap_allocated());
|
||||||
///
|
///
|
||||||
/// let s2 = InliningString::<22>::new("This string is 23 bytes");
|
/// let s2 = InliningString::<22>::new("This string is 23 bytes");
|
||||||
/// assert_eq!(&*s2, "This string is 23 bytes");
|
/// assert_eq!(&*s2, "This string is 23 bytes");
|
||||||
/// assert!(s2.heap_allocated());
|
/// assert!(s2.heap_allocated());
|
||||||
@@ -51,7 +57,7 @@ pub struct InliningString<const N: usize>(Repr<N>);
|
|||||||
impl<const N: usize> InliningString<N> {
|
impl<const N: usize> InliningString<N> {
|
||||||
/// Creates a new `InliningString` from the given string, storing the string data inline if
|
/// Creates a new `InliningString` from the given string, storing the string data inline if
|
||||||
/// possible or creating a new heap allocation otherwise.
|
/// possible or creating a new heap allocation otherwise.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use libshire::strings::InliningString;
|
/// # use libshire::strings::InliningString;
|
||||||
/// let s = InliningString::<22>::new("Hello, InliningString!");
|
/// let s = InliningString::<22>::new("Hello, InliningString!");
|
||||||
@@ -71,7 +77,7 @@ impl<const N: usize> InliningString<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new empty `InliningString`.
|
/// Returns a new empty `InliningString`.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use libshire::strings::InliningString;
|
/// # use libshire::strings::InliningString;
|
||||||
/// let s = InliningString::<22>::empty();
|
/// let s = InliningString::<22>::empty();
|
||||||
@@ -103,6 +109,15 @@ impl<const N: usize> InliningString<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub fn into_boxed_str(self) -> Box<str> {
|
||||||
|
match self {
|
||||||
|
Self(Repr::Inline(buf)) => buf.into_boxed_str(),
|
||||||
|
Self(Repr::Boxed(buf)) => buf,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Consumes the `InliningString` and converts it to a heap-allocated `String`.
|
/// Consumes the `InliningString` and converts it to a heap-allocated `String`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@@ -114,7 +129,7 @@ impl<const N: usize> InliningString<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the length of the string in bytes.
|
/// Returns the length of the string in bytes.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use libshire::strings::InliningString;
|
/// # use libshire::strings::InliningString;
|
||||||
/// let s = InliningString::<22>::new("こんにちは");
|
/// let s = InliningString::<22>::new("こんにちは");
|
||||||
@@ -130,12 +145,12 @@ impl<const N: usize> InliningString<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the string has length 0.
|
/// Returns `true` if the string has length 0.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use libshire::strings::InliningString;
|
/// # use libshire::strings::InliningString;
|
||||||
/// let s1 = InliningString::<22>::new("");
|
/// let s1 = InliningString::<22>::new("");
|
||||||
/// assert!(s1.is_empty());
|
/// assert!(s1.is_empty());
|
||||||
///
|
///
|
||||||
/// let s2 = InliningString::<22>::new("Hello");
|
/// let s2 = InliningString::<22>::new("Hello");
|
||||||
/// assert!(!s2.is_empty());
|
/// assert!(!s2.is_empty());
|
||||||
/// ```
|
/// ```
|
||||||
@@ -149,12 +164,12 @@ impl<const N: usize> InliningString<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the string data is stored on the heap, and `false` otherwise.
|
/// Returns `true` if the string data is stored on the heap, and `false` otherwise.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use libshire::strings::InliningString;
|
/// # use libshire::strings::InliningString;
|
||||||
/// let s1 = InliningString::<22>::new("This string's 22 bytes");
|
/// let s1 = InliningString::<22>::new("This string's 22 bytes");
|
||||||
/// assert!(!s1.heap_allocated());
|
/// assert!(!s1.heap_allocated());
|
||||||
///
|
///
|
||||||
/// let s2 = InliningString::<22>::new("This string is 23 bytes");
|
/// let s2 = InliningString::<22>::new("This string is 23 bytes");
|
||||||
/// assert!(s2.heap_allocated());
|
/// assert!(s2.heap_allocated());
|
||||||
/// ```
|
/// ```
|
||||||
@@ -304,7 +319,7 @@ impl<const N: usize> fmt::Display for InliningString<N> {
|
|||||||
impl<const N: usize> serde::Serialize for InliningString<N> {
|
impl<const N: usize> serde::Serialize for InliningString<N> {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
serde::Serialize::serialize(&**self, serializer)
|
serde::Serialize::serialize(&**self, serializer)
|
||||||
}
|
}
|
||||||
@@ -314,10 +329,9 @@ impl<const N: usize> serde::Serialize for InliningString<N> {
|
|||||||
impl<'de, const N: usize> serde::Deserialize<'de> for InliningString<N> {
|
impl<'de, const N: usize> serde::Deserialize<'de> for InliningString<N> {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: serde::Deserializer<'de>
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
serde::Deserialize::deserialize(deserializer)
|
serde::Deserialize::deserialize(deserializer).map(Self::new::<Cow<'de, str>>)
|
||||||
.map(Self::new::<&'de str>)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,6 +343,10 @@ enum Repr<const N: usize> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::borrow::{Cow, ToOwned};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use super::{InliningString, InliningString22};
|
use super::{InliningString, InliningString22};
|
||||||
@@ -341,7 +359,7 @@ mod tests {
|
|||||||
"Somethingfortheweekend",
|
"Somethingfortheweekend",
|
||||||
"Dichlorodifluoromethane",
|
"Dichlorodifluoromethane",
|
||||||
"こんにちは",
|
"こんにちは",
|
||||||
"❤️🧡💛💚💙💜"
|
"❤️🧡💛💚💙💜",
|
||||||
];
|
];
|
||||||
|
|
||||||
for s in test_strings {
|
for s in test_strings {
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
pub mod experimental;
|
pub mod experimental;
|
||||||
pub mod fixed;
|
pub mod fixed;
|
||||||
pub mod capped;
|
pub mod capped;
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
pub mod inlining;
|
pub mod inlining;
|
||||||
|
|
||||||
pub use fixed::{FixedString, Error as FixedStringError};
|
pub use fixed::{FixedString, Error as FixedStringError};
|
||||||
pub use capped::{CappedString, Error as CappedStringError};
|
pub use capped::{CappedString, Error as CappedStringError};
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
pub use inlining::{InliningString, InliningString22};
|
pub use inlining::{InliningString, InliningString22};
|
||||||
+9
-3
@@ -1,4 +1,4 @@
|
|||||||
use std::{error, fmt, str};
|
use core::{fmt, str};
|
||||||
|
|
||||||
use crate::{hex, strings::FixedString};
|
use crate::{hex, strings::FixedString};
|
||||||
|
|
||||||
@@ -222,7 +222,8 @@ impl fmt::Display for ParseError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for ParseError {}
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for ParseError {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum UuidV5Error {
|
pub enum UuidV5Error {
|
||||||
@@ -237,7 +238,8 @@ impl fmt::Display for UuidV5Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for UuidV5Error {}
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for UuidV5Error {}
|
||||||
|
|
||||||
fn sha1(namespace: [u8; 16], name: &[u8]) -> Result<[u8; 20], UuidV5Error> {
|
fn sha1(namespace: [u8; 16], name: &[u8]) -> Result<[u8; 20], UuidV5Error> {
|
||||||
let (mut h0, mut h1, mut h2, mut h3, mut h4) = (
|
let (mut h0, mut h1, mut h2, mut h3, mut h4) = (
|
||||||
@@ -410,8 +412,12 @@ impl<'a> Iterator for Sha1ChunkIter<'a> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::Uuid;
|
use super::Uuid;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uuid_display() {
|
fn test_uuid_display() {
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::string::ToString;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Uuid::from_bytes([
|
Uuid::from_bytes([
|
||||||
0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, 0xd3, 0xa4, 0x56, 0x42, 0x66, 0x14, 0x17,
|
0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, 0xd3, 0xa4, 0x56, 0x42, 0x66, 0x14, 0x17,
|
||||||
|
|||||||
Reference in new issue
Block a user