mirror of
https://github.com/fafhrd91/actix-net
synced 2024-11-23 21:51:06 +01:00
prepare bytestring release 1.0.0 (#243)
This commit is contained in:
parent
647817ef14
commit
14ff379150
@ -1,30 +1,36 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2020-xx-xx
|
||||
* Update `bytes` dependency to `1`
|
||||
|
||||
## [0.1.5] - 2020-03-30
|
||||
|
||||
## 1.0.0 - 2020-12-31
|
||||
* Update `bytes` dependency to `1`.
|
||||
* Add array and slice of `u8` impls of `TryFrom` up to 32 in length.
|
||||
* Rename `get_ref` to `as_bytes` and rename `into_inner` to `into_bytes`.
|
||||
* `ByteString::new` is now a `const fn`.
|
||||
* Crate is now `#[no_std]` compatible.
|
||||
|
||||
|
||||
## 0.1.5 - 2020-03-30
|
||||
* Serde support
|
||||
|
||||
## [0.1.4] - 2020-01-14
|
||||
|
||||
## 0.1.4 - 2020-01-14
|
||||
* Fix `AsRef<str>` impl
|
||||
|
||||
## [0.1.3] - 2020-01-13
|
||||
|
||||
## 0.1.3 - 2020-01-13
|
||||
* Add `PartialEq<T: AsRef<str>>`, `AsRef<[u8]>` impls
|
||||
|
||||
## [0.1.2] - 2019-12-22
|
||||
|
||||
## 0.1.2 - 2019-12-22
|
||||
* Fix `new()` method
|
||||
|
||||
* Make `ByteString::from_static()` and `ByteString::from_bytes_unchecked()` methods const.
|
||||
|
||||
## [0.1.1] - 2019-12-07
|
||||
|
||||
## 0.1.1 - 2019-12-07
|
||||
* Fix hash impl
|
||||
|
||||
## [0.1.0] - 2019-12-07
|
||||
|
||||
## 0.1.0 - 2019-12-07
|
||||
* Initial release
|
||||
|
@ -1,9 +1,13 @@
|
||||
[package]
|
||||
name = "bytestring"
|
||||
version = "0.1.5"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "A UTF-8 encoded string with Bytes as a storage"
|
||||
keywords = ["actix"]
|
||||
version = "1.0.0"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
]
|
||||
description = "An immutable UTF-8 encoded string using Bytes as storage"
|
||||
keywords = ["string", "bytes", "utf8", "web-programming", "actix"]
|
||||
categories = ["no-std", "web-programming"]
|
||||
homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
documentation = "https://docs.rs/bytestring/"
|
||||
@ -19,4 +23,5 @@ bytes = "1"
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0"
|
||||
serde_json = "1.0"
|
||||
siphasher = "0.3"
|
||||
|
@ -1,37 +1,38 @@
|
||||
//! A UTF-8 encoded read-only string using Bytes as storage.
|
||||
|
||||
#![no_std]
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::{borrow, fmt, hash, ops, str};
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::{borrow, convert::TryFrom, fmt, hash, ops, str};
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
/// A UTF-8 encoded string with [`Bytes`] as a storage.
|
||||
///
|
||||
/// [`Bytes`]: bytes::Bytes
|
||||
#[derive(Clone, Eq, Ord, PartialOrd, Default)]
|
||||
/// An immutable UTF-8 encoded string with [`Bytes`] as a storage.
|
||||
#[derive(Clone, Default, Eq, PartialOrd, Ord)]
|
||||
pub struct ByteString(Bytes);
|
||||
|
||||
impl ByteString {
|
||||
/// Creates a new `ByteString`.
|
||||
pub fn new() -> Self {
|
||||
/// Creates a new empty `ByteString`.
|
||||
pub const fn new() -> Self {
|
||||
ByteString(Bytes::new())
|
||||
}
|
||||
|
||||
/// Get a reference to the underlying bytes object.
|
||||
pub fn get_ref(&self) -> &Bytes {
|
||||
/// Get a reference to the underlying `Bytes` object.
|
||||
pub fn as_bytes(&self) -> &Bytes {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Unwraps this `ByteString`, returning the underlying bytes object.
|
||||
pub fn into_inner(self) -> Bytes {
|
||||
/// Unwraps this `ByteString` into the underlying `Bytes` object.
|
||||
pub fn into_bytes(self) -> Bytes {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Creates a new `ByteString` from a static str.
|
||||
/// Creates a new `ByteString` from a `&'static str`.
|
||||
pub const fn from_static(src: &'static str) -> ByteString {
|
||||
Self(Bytes::from_static(src.as_bytes()))
|
||||
}
|
||||
@ -39,11 +40,10 @@ impl ByteString {
|
||||
/// Creates a new `ByteString` from a Bytes.
|
||||
///
|
||||
/// # Safety
|
||||
/// This function is unsafe because it does not check the bytes passed to it
|
||||
/// are valid UTF-8. If this constraint is violated,
|
||||
/// it may cause memory unsafety issues with future users of the `ByteString`,
|
||||
/// as we assume that `ByteString`s are valid UTF-8.
|
||||
/// However, the most likely issue is that the data gets corrupted.
|
||||
/// This function is unsafe because it does not check the bytes passed to it are valid UTF-8.
|
||||
/// If this constraint is violated, it may cause memory unsafety issues with future users of
|
||||
/// the `ByteString`, as we assume that `ByteString`s are valid UTF-8. However, the most likely
|
||||
/// issue is that the data gets corrupted.
|
||||
pub const unsafe fn from_bytes_unchecked(src: Bytes) -> ByteString {
|
||||
Self(src)
|
||||
}
|
||||
@ -84,8 +84,10 @@ impl ops::Deref for ByteString {
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
let b = self.0.as_ref();
|
||||
unsafe { str::from_utf8_unchecked(b) }
|
||||
let bytes = self.0.as_ref();
|
||||
// SAFETY:
|
||||
// UTF-8 validity is guaranteed at during construction.
|
||||
unsafe { str::from_utf8_unchecked(bytes) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,21 +98,24 @@ impl borrow::Borrow<str> for ByteString {
|
||||
}
|
||||
|
||||
impl From<String> for ByteString {
|
||||
#[inline]
|
||||
fn from(value: String) -> Self {
|
||||
Self(Bytes::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for ByteString {
|
||||
fn from(value: &'a str) -> Self {
|
||||
impl From<&str> for ByteString {
|
||||
#[inline]
|
||||
fn from(value: &str) -> Self {
|
||||
Self(Bytes::copy_from_slice(value.as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a [u8]> for ByteString {
|
||||
impl TryFrom<&[u8]> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
|
||||
#[inline]
|
||||
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
|
||||
let _ = str::from_utf8(value)?;
|
||||
Ok(ByteString(Bytes::copy_from_slice(value)))
|
||||
}
|
||||
@ -119,15 +124,17 @@ impl<'a> TryFrom<&'a [u8]> for ByteString {
|
||||
impl TryFrom<Vec<u8>> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||
let _ = str::from_utf8(value.as_ref())?;
|
||||
Ok(ByteString(Bytes::from(value)))
|
||||
let buf = String::from_utf8(value).map_err(|err| err.utf8_error())?;
|
||||
Ok(ByteString(Bytes::from(buf)))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Bytes> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
|
||||
let _ = str::from_utf8(value.as_ref())?;
|
||||
Ok(ByteString(value))
|
||||
@ -137,8 +144,9 @@ impl TryFrom<Bytes> for ByteString {
|
||||
impl TryFrom<bytes::BytesMut> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: bytes::BytesMut) -> Result<Self, Self::Error> {
|
||||
let _ = str::from_utf8(value.as_ref())?;
|
||||
let _ = str::from_utf8(&value)?;
|
||||
Ok(ByteString(value.freeze()))
|
||||
}
|
||||
}
|
||||
@ -146,10 +154,20 @@ impl TryFrom<bytes::BytesMut> for ByteString {
|
||||
macro_rules! array_impls {
|
||||
($($len:expr)+) => {
|
||||
$(
|
||||
impl<'a> TryFrom<&'a [u8; $len]> for ByteString {
|
||||
impl TryFrom<[u8; $len]> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
fn try_from(value: &'a [u8; $len]) -> Result<Self, Self::Error> {
|
||||
#[inline]
|
||||
fn try_from(value: [u8; $len]) -> Result<Self, Self::Error> {
|
||||
ByteString::try_from(&value[..])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8; $len]> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: &[u8; $len]) -> Result<Self, Self::Error> {
|
||||
ByteString::try_from(&value[..])
|
||||
}
|
||||
}
|
||||
@ -157,7 +175,7 @@ macro_rules! array_impls {
|
||||
}
|
||||
}
|
||||
|
||||
array_impls!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16);
|
||||
array_impls!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32);
|
||||
|
||||
impl fmt::Debug for ByteString {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -173,6 +191,8 @@ impl fmt::Display for ByteString {
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde {
|
||||
use alloc::string::String;
|
||||
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
|
||||
@ -201,16 +221,19 @@ mod serde {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use alloc::borrow::ToOwned;
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
||||
use siphasher::sip::SipHasher;
|
||||
|
||||
use super::*;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[test]
|
||||
fn test_partial_eq() {
|
||||
let s: ByteString = ByteString::from_static("test");
|
||||
assert_eq!(s, "test");
|
||||
assert_eq!(s, *"test");
|
||||
assert_eq!(s, "test".to_string());
|
||||
assert_eq!(s, "test".to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -220,10 +243,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_hash() {
|
||||
let mut hasher1 = DefaultHasher::default();
|
||||
let mut hasher1 = SipHasher::default();
|
||||
"str".hash(&mut hasher1);
|
||||
|
||||
let mut hasher2 = DefaultHasher::default();
|
||||
let mut hasher2 = SipHasher::default();
|
||||
let s = ByteString::from_static("str");
|
||||
s.hash(&mut hasher2);
|
||||
assert_eq!(hasher1.finish(), hasher2.finish());
|
||||
@ -231,7 +254,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_from_string() {
|
||||
let s: ByteString = "hello".to_string().into();
|
||||
let s: ByteString = "hello".to_owned().into();
|
||||
assert_eq!(&s, "hello");
|
||||
let t: &str = s.as_ref();
|
||||
assert_eq!(t, "hello");
|
||||
@ -249,17 +272,25 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_rbytes() {
|
||||
fn test_try_from_slice() {
|
||||
let _ = ByteString::try_from(b"nice bytes").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_array() {
|
||||
assert_eq!(
|
||||
ByteString::try_from([b'h', b'i']).unwrap(),
|
||||
ByteString::from_static("hi")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_bytes() {
|
||||
let _ = ByteString::try_from(Bytes::from_static(b"nice bytes")).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_bytesmut() {
|
||||
fn test_try_from_bytes_mut() {
|
||||
let _ = ByteString::try_from(bytes::BytesMut::from(&b"nice bytes"[..])).unwrap();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user