| // Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT | ||
| // file at the top-level directory of this distribution and at | ||
| // http://rust-lang.org/COPYRIGHT. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
| // | ||
| // Original authors: alexchrichton | ||
| // UTF-8 ranges and tags for encoding characters | ||
| const TAG_CONT: u8 = 0b1000_0000; | ||
| const TAG_TWO_B: u8 = 0b1100_0000; | ||
| const TAG_THREE_B: u8 = 0b1110_0000; | ||
| const TAG_FOUR_B: u8 = 0b1111_0000; | ||
| const MAX_ONE_B: u32 = 0x80; | ||
| const MAX_TWO_B: u32 = 0x800; | ||
| const MAX_THREE_B: u32 = 0x10000; | ||
| /// Placeholder | ||
| pub struct EncodeError; | ||
| /// Encode a char into buf | ||
| #[inline] | ||
| pub fn encode_utf8(ch: char, buf: &mut [u8]) -> Result<usize, EncodeError> | ||
| { | ||
| let code = ch as u32; | ||
| if code < MAX_ONE_B && buf.len() >= 1 { | ||
| buf[0] = code as u8; | ||
| return Ok(1); | ||
| } else if code < MAX_TWO_B && buf.len() >= 2 { | ||
| buf[0] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; | ||
| buf[1] = (code & 0x3F) as u8 | TAG_CONT; | ||
| return Ok(2); | ||
| } else if code < MAX_THREE_B && buf.len() >= 3 { | ||
| buf[0] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; | ||
| buf[1] = (code >> 6 & 0x3F) as u8 | TAG_CONT; | ||
| buf[2] = (code & 0x3F) as u8 | TAG_CONT; | ||
| return Ok(3); | ||
| } else if buf.len() >= 4 { | ||
| buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; | ||
| buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT; | ||
| buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; | ||
| buf[3] = (code & 0x3F) as u8 | TAG_CONT; | ||
| return Ok(4); | ||
| }; | ||
| Err(EncodeError) | ||
| } | ||
+2
-2
| [package] | ||
| name = "arrayvec" | ||
| version = "0.3.19" | ||
| version = "0.3.20" | ||
| authors = ["bluss"] | ||
@@ -8,3 +8,3 @@ license = "MIT/Apache-2.0" | ||
| description = "A vector with a fixed capacity, it can be stored on the stack too. Implements fixed capacity ArrayVec and ArrayString." | ||
| documentation = "http://bluss.github.io/arrayvec" | ||
| documentation = "https://docs.rs/arrayvec/" | ||
| repository = "https://github.com/bluss/arrayvec" | ||
@@ -11,0 +11,0 @@ |
+4
-0
@@ -25,2 +25,6 @@ | ||
| - 0.3.20 | ||
| - Simplify and speed up ``ArrayString``’s ``.push(char)``- | ||
| - 0.3.19 | ||
@@ -27,0 +31,0 @@ |
+19
-2
@@ -13,2 +13,3 @@ use std::borrow::Borrow; | ||
| use CapacityError; | ||
| use char_ext::encode_utf8; | ||
@@ -112,4 +113,12 @@ /// A string with a fixed capacity. | ||
| pub fn push(&mut self, c: char) -> Result<(), CapacityError<char>> { | ||
| use std::fmt::Write; | ||
| self.write_char(c).map_err(|_| CapacityError::new(c)) | ||
| let len = self.len(); | ||
| unsafe { | ||
| match encode_utf8(c, &mut self.raw_mut_bytes()[len..]) { | ||
| Ok(n) => { | ||
| self.set_len(len + n); | ||
| Ok(()) | ||
| } | ||
| Err(_) => Err(CapacityError::new(c)), | ||
| } | ||
| } | ||
| } | ||
@@ -174,2 +183,7 @@ | ||
| } | ||
| /// Return a mutable slice of the whole string's buffer | ||
| unsafe fn raw_mut_bytes(&mut self) -> &mut [u8] { | ||
| slice::from_raw_parts_mut(self.xs.as_mut_ptr(), self.capacity()) | ||
| } | ||
| } | ||
@@ -243,2 +257,5 @@ | ||
| impl<A: Array<Item=u8>> fmt::Write for ArrayString<A> { | ||
| fn write_char(&mut self, c: char) -> fmt::Result { | ||
| self.push(c).map_err(|_| fmt::Error) | ||
| } | ||
| fn write_str(&mut self, s: &str) -> fmt::Result { | ||
@@ -245,0 +262,0 @@ self.push_str(s).map_err(|_| fmt::Error) |
+2
-0
@@ -22,2 +22,3 @@ //! **arrayvec** provides the types `ArrayVec` and `ArrayString`: | ||
| //! size array for ArrayVec storage. | ||
| #![doc(html_root_url="https://docs.rs/arrayvec/0.3/")] | ||
| #![cfg_attr(not(feature="std"), no_std)] | ||
@@ -59,2 +60,3 @@ extern crate odds; | ||
| mod array_string; | ||
| mod char_ext; | ||
@@ -61,0 +63,0 @@ pub use array::Array; |
+15
-0
@@ -359,3 +359,18 @@ extern crate arrayvec; | ||
| #[test] | ||
| fn test_string_push() { | ||
| let text = "abcαβγ"; | ||
| let mut s = ArrayString::<[_; 8]>::new(); | ||
| for c in text.chars() { | ||
| if let Err(_) = s.push(c) { | ||
| break; | ||
| } | ||
| } | ||
| assert_eq!("abcαβ", &s[..]); | ||
| s.push('x').ok(); | ||
| assert_eq!("abcαβx", &s[..]); | ||
| assert!(s.push('x').is_err()); | ||
| } | ||
| #[test] | ||
@@ -362,0 +377,0 @@ fn test_insert_at_length() { |