#![deny(missing_docs)]
#[cfg(feature="use_serde")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature="use_serde")]
extern crate serde;
use std::borrow;
use std::fmt;
use std::io::Write;
use std::mem::transmute;
use std::ops;
use std::ptr;
use std::str;
use std::cmp;
use std::hash;
#[cfg(feature="use_serde")]
use serde::de::Error;
#[derive(Copy, Default)]
pub struct StringWrapper<T>
where T: Buffer
{
len: usize,
buffer: T,
}
pub unsafe trait Buffer {
fn as_ref(&self) -> &[u8];
fn as_mut(&mut self) -> &mut [u8];
}
pub trait OwnedBuffer: Buffer {
fn new() -> Self;
}
impl<T> StringWrapper<T>
where T: Buffer
{
pub fn new(buffer: T) -> Self {
StringWrapper {
len: 0,
buffer: buffer,
}
}
pub unsafe fn from_raw_parts(buffer: T, len: usize) -> Self {
StringWrapper {
len: len,
buffer: buffer,
}
}
pub fn into_buffer(self) -> T {
self.buffer
}
pub fn buffer(&self) -> &[u8] {
self.buffer.as_ref()
}
pub unsafe fn buffer_mut(&mut self) -> &mut [u8] {
self.buffer.as_mut()
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub unsafe fn set_len(&mut self, new_len: usize) {
self.len = new_len
}
pub fn truncate(&mut self, new_len: usize) {
assert!(new_len <= self.len);
if new_len < self.len {
assert!(starts_well_formed_utf8_sequence(self.buffer.as_ref()[new_len]));
}
self.len = new_len;
}
pub fn capacity(&self) -> usize {
self.buffer.as_ref().len()
}
pub fn extra_capacity(&self) -> usize {
self.capacity() - self.len
}
pub fn extra_bytes_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[self.len..]
}
pub fn push(&mut self, c: char) -> Result<(), ()> {
let new_len = self.len + c.len_utf8();
if new_len <= self.capacity() {
write!(self.extra_bytes_mut(), "{}", c).unwrap();
self.len = new_len;
Ok(())
} else {
Err(())
}
}
pub fn push_str(&mut self, s: &str) {
copy_memory(s.as_bytes(), self.extra_bytes_mut());
self.len += s.len();
}
pub fn push_partial_str(&mut self, s: &str) -> Result<(), usize> {
let mut i = self.extra_capacity();
let (s, result) = if i < s.len() {
while !starts_well_formed_utf8_sequence(s.as_bytes()[i]) {
i -= 1
}
(&s[..i], Err(i))
} else {
(s, Ok(()))
};
self.push_str(s);
result
}
}
impl<T: OwnedBuffer> StringWrapper<T> {
pub fn from_str(s: &str) -> StringWrapper<T> {
let buffer = T::new();
let mut sw = StringWrapper::new(buffer);
sw.push_str(s);
sw
}
pub fn from_str_safe(s: &str) -> Option<StringWrapper<T>> {
let buffer = T::new();
let mut sw = StringWrapper::new(buffer);
match sw.push_partial_str(s) {
Ok(_) => Some(sw),
Err(_) => None,
}
}
}
fn starts_well_formed_utf8_sequence(byte: u8) -> bool {
byte < 128 || byte >= 192
}
fn copy_memory(src: &[u8], dst: &mut [u8]) {
let len_src = src.len();
assert!(dst.len() >= len_src);
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), len_src);
}
}
impl<T> ops::Deref for StringWrapper<T>
where T: Buffer
{
type Target = str;
fn deref(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.buffer.as_ref()[..self.len]) }
}
}
impl<T> ops::DerefMut for StringWrapper<T>
where T: Buffer
{
fn deref_mut(&mut self) -> &mut str {
unsafe { transmute::<&mut [u8], &mut str>(&mut self.buffer.as_mut()[..self.len]) }
}
}
impl<T> borrow::Borrow<str> for StringWrapper<T>
where T: Buffer
{
fn borrow(&self) -> &str {
self
}
}
impl<T> fmt::Display for StringWrapper<T>
where T: Buffer
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T> fmt::Debug for StringWrapper<T>
where T: Buffer
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: Buffer> PartialEq for StringWrapper<T> {
fn eq(&self, other: &Self) -> bool {
**self == **other
}
}
impl<T: Buffer> Eq for StringWrapper<T> {}
impl<T: Buffer + Copy> Clone for StringWrapper<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: Buffer> PartialOrd for StringWrapper<T> {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T: Buffer> hash::Hash for StringWrapper<T> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<T: Buffer> Ord for StringWrapper<T> {
fn cmp(&self, other: &Self) -> cmp::Ordering {
(**self).cmp(&**other)
}
}
#[cfg(feature="use_serde")]
impl<T: Buffer> serde::Serialize for StringWrapper<T> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.to_string().serialize(serializer)
}
}
#[cfg(feature="use_serde")]
impl<'de, T: OwnedBuffer> serde::Deserialize<'de> for StringWrapper<T> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s: String = serde::Deserialize::deserialize(deserializer)?;
let sb = StringWrapper::from_str_safe(&s).ok_or_else(|| {
let buff = T::new();
let msg: String = format!("string that can fit into {} bytes", buff.as_ref().len());
D::Error::invalid_length(s.len(), &StringExpected(msg))
})?;
Ok(sb)
}
}
#[cfg(feature="use_serde")]
struct StringExpected(String);
#[cfg(feature="use_serde")]
impl serde::de::Expected for StringExpected {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, formatter)
}
}
unsafe impl<'a, T: ?Sized + Buffer> Buffer for &'a mut T {
fn as_ref(&self) -> &[u8] {
(**self).as_ref()
}
fn as_mut(&mut self) -> &mut [u8] {
(**self).as_mut()
}
}
unsafe impl<'a, T: ?Sized + Buffer> Buffer for Box<T> {
fn as_ref(&self) -> &[u8] {
(**self).as_ref()
}
fn as_mut(&mut self) -> &mut [u8] {
(**self).as_mut()
}
}
unsafe impl Buffer for Vec<u8> {
fn as_ref(&self) -> &[u8] {
self
}
fn as_mut(&mut self) -> &mut [u8] {
self
}
}
unsafe impl Buffer for [u8] {
fn as_ref(&self) -> &[u8] {
self
}
fn as_mut(&mut self) -> &mut [u8] {
self
}
}
macro_rules! array_impl {
($($N: expr)+) => {
$(
unsafe impl Buffer for [u8; $N] {
fn as_ref(&self) -> &[u8] { self }
fn as_mut(&mut self) -> &mut [u8] { self }
}
impl OwnedBuffer for [u8; $N] {
fn new() -> Self { [0u8; $N] }
}
)+
}
}
array_impl! {
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
64 128 256 512 1024
2 * 1024
4 * 1024
8 * 1024
16 * 1024
32 * 1024
64 * 1024
128 * 1024
256 * 1024
512 * 1024
1024 * 1024
2 * 1024 * 1024
4 * 1024 * 1024
8 * 1024 * 1024
16 * 1024 * 1024
32 * 1024 * 1024
64 * 1024 * 1024
128 * 1024 * 1024
256 * 1024 * 1024
512 * 1024 * 1024
1024 * 1024 * 1024
100 1_000 10_000 100_000 1_000_000
10_000_000 100_000_000 1_000_000_000
}
#[cfg(test)]
mod tests {
use std;
use std::cmp;
use std::hash;
#[cfg(feature="use_serde")]
extern crate serde_json;
use StringWrapper;
#[test]
fn traits() {
#[derive(Eq, PartialEq, Ord, PartialOrd)]
struct Foo {
x: StringWrapper<[u8; 64]>,
}
}
#[test]
fn eq() {
let mut s = StringWrapper::<[u8; 3]>::new(*b"000");
assert_eq!(s, s);
s.push_str("foo");
let mut s2 = StringWrapper::<[u8; 3]>::new(*b"000");
s2.push_str("foo");
assert_eq!(s, s2);
let mut s3 = StringWrapper::<[u8; 3]>::new(*b"000");
s3.push_str("bar");
assert!(s != s3);
}
#[test]
fn eq_only_to_length() {
let a = StringWrapper::<[u8; 5]>::new(*b"aaaaa");
let b = StringWrapper::<[u8; 5]>::new(*b"bbbbb");
assert_eq!(a, b);
}
#[test]
fn ord() {
let mut s = StringWrapper::<[u8; 3]>::new(*b"000");
let mut s2 = StringWrapper::<[u8; 3]>::new(*b"000");
s.push_str("a");
s2.push_str("b");
assert_eq!(s.partial_cmp(&s2), Some(cmp::Ordering::Less));
assert_eq!(s.cmp(&s2), cmp::Ordering::Less);
}
#[test]
fn ord_only_to_length() {
let mut s = StringWrapper::<[u8; 3]>::new(*b"000");
let mut s2 = StringWrapper::<[u8; 3]>::new(*b"111");
assert_eq!(s.partial_cmp(&s2), Some(cmp::Ordering::Equal));
assert_eq!(s.cmp(&s2), cmp::Ordering::Equal);
s.push_str("aa");
s2.push_str("aa");
assert_eq!(s.partial_cmp(&s2), Some(cmp::Ordering::Equal));
assert_eq!(s.cmp(&s2), cmp::Ordering::Equal);
}
#[cfg(test)]
fn hash<T: hash::Hash>(t: &T) -> u64 {
let mut h = std::collections::hash_map::DefaultHasher::new();
t.hash(&mut h);
hash::Hasher::finish(&h)
}
#[test]
fn hash_only_to_length() {
let mut s = StringWrapper::<[u8; 64]>::new([0u8; 64]);
let mut s2 = StringWrapper::<[u8; 64]>::new([1u8; 64]);
assert_eq!(hash(&s), hash(&s2));
s.push_str("a");
assert!(hash(&s) != hash(&s2));
s2.push_str("a");
assert_eq!(hash(&s), hash(&s2));
}
#[test]
fn from_str() {
let s: StringWrapper<[u8; 64]> = StringWrapper::from_str("OMG!");
let mut s2 = StringWrapper::new([0u8; 64]);
s2.push_str("OMG!");
assert_eq!(s, s2);
}
#[test]
fn it_works() {
let mut s = StringWrapper::new([0; 10]);
assert_eq!(&*s, "");
assert_eq!(s.len(), 0);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 10);
assert_eq!(&*s, "");
assert_eq!(s.len(), 0);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 10);
s.push_str("a");
assert_eq!(&*s, "a");
assert_eq!(s.len(), 1);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 9);
assert_eq!(s.push('é'), Ok(()));
assert_eq!(&*s, "aé");
assert_eq!(s.len(), 3);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 7);
assert_eq!(s.push_partial_str("~~~"), Ok(()));
assert_eq!(&*s, "aé~~~");
assert_eq!(s.len(), 6);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 4);
assert_eq!(s.push_partial_str("hello"), Err(4));
assert_eq!(&*s, "aé~~~hell");
assert_eq!(s.len(), 10);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 0);
s.truncate(6);
assert_eq!(&*s, "aé~~~");
assert_eq!(s.len(), 6);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 4);
assert_eq!(s.push_partial_str("_🌠"), Err(1));
assert_eq!(&*s, "aé~~~_");
assert_eq!(s.len(), 7);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 3);
assert_eq!(s.push('🌠'), Err(()));
assert_eq!(&*s, "aé~~~_");
assert_eq!(s.len(), 7);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 3);
let buffer: [u8; 10] = s.clone().into_buffer();
assert_eq!(&buffer, b"a\xC3\xA9~~~_ell");
assert_eq!(format!("{}", s), "aé~~~_");
assert_eq!(format!("{:?}", s), r#""aé~~~_""#);
assert_eq!(s.push_partial_str("ô!?"), Err(3));
assert_eq!(&*s, "aé~~~_ô!");
assert_eq!(s.len(), 10);
assert_eq!(s.capacity(), 10);
assert_eq!(s.extra_capacity(), 0);
}
#[cfg(feature="use_serde")]
#[test]
fn test_serde() {
let mut s = StringWrapper::new([0u8; 64]);
s.push_str("foobar");
let json = serde_json::to_string(&s).unwrap();
assert_eq!(json, "\"foobar\"");
let s2 = serde_json::from_str(&json).unwrap();
assert_eq!(s, s2);
}
#[cfg(feature="use_serde")]
#[test]
fn deserialize_too_long() {
let json = "\"12345\"";
match serde_json::from_str::<StringWrapper<[u8; 3]>>(&json) {
Err(e) => {
assert_eq!(format!("{}", e),
"invalid length 5, expected string that can fit into 3 bytes")
}
Ok(x) => panic!("Expected error, got success: {:?}", x),
}
}
#[test]
fn clone() {
let s = StringWrapper::new([0u8; 64]);
let y: StringWrapper<[u8; 64]> = s.clone();
println!("s: {}, y: {}", s, y);
}
}