pub use crate::external_string::ExternalString;
pub use crate::semver_string::String;
pub use crate::version::PinnedVersion;
pub use crate::version::Version;
pub use crate::version::VersionType;
pub use crate::semver_query::Query;
pub use crate::semver_range::Range;
pub use crate::sliced_string::SlicedString;
#[path = "SemverQuery.rs"]
pub mod semver_query;
#[path = "SemverRange.rs"]
pub mod semver_range;
#[path = "Version.rs"]
pub mod version;
pub use crate::semver_query as query;
pub use crate::semver_range as range;
pub trait Slicable {
fn slice<'a>(&'a self, buf: &'a [u8]) -> &'a [u8];
}
impl Slicable for crate::semver_string::String {
#[inline]
fn slice<'a>(&'a self, buf: &'a [u8]) -> &'a [u8] {
crate::semver_string::String::slice(self, buf)
}
}
impl Slicable for crate::external_string::ExternalString {
#[inline]
fn slice<'a>(&'a self, buf: &'a [u8]) -> &'a [u8] {
crate::external_string::ExternalString::slice(self, buf)
}
}
pub use crate::semver_string as string;
pub trait StringBuilder {
fn count(&mut self, slice_: &[u8]);
fn append<T: crate::semver_string::BuilderStringType>(&mut self, slice_: &[u8]) -> T;
#[inline]
fn append_string(&mut self, s: &[u8]) -> crate::semver_string::String {
self.append::<crate::semver_string::String>(s)
}
#[inline]
fn append_external_string(&mut self, s: &[u8]) -> crate::external_string::ExternalString {
self.append::<crate::external_string::ExternalString>(s)
}
}
impl StringBuilder for crate::semver_string::Builder {
#[inline]
fn count(&mut self, slice_: &[u8]) {
crate::semver_string::Builder::count(self, slice_)
}
#[inline]
fn append<T: crate::semver_string::BuilderStringType>(&mut self, slice_: &[u8]) -> T {
crate::semver_string::Builder::append::<T>(self, slice_)
}
}
pub mod sliced_string {
use super::external_string::ExternalString;
use super::semver_string::String;
#[derive(Copy, Clone)]
pub struct SlicedString<'a> {
pub buf: &'a [u8],
pub slice: &'a [u8],
}
impl<'a> SlicedString<'a> {
#[inline]
pub fn init(buf: &'a [u8], slice: &'a [u8]) -> SlicedString<'a> {
if cfg!(debug_assertions) {
if (buf.as_ptr() as usize) > (slice.as_ptr() as usize) {
panic!("SlicedString.init buf is not in front of slice");
}
}
SlicedString { buf, slice }
}
#[inline]
pub fn external(self) -> ExternalString {
debug_assert!(
(self.buf.as_ptr() as usize) <= (self.slice.as_ptr() as usize)
&& ((self.slice.as_ptr() as usize) + self.slice.len())
<= ((self.buf.as_ptr() as usize) + self.buf.len())
);
ExternalString::init(
self.buf,
self.slice,
bun_wyhash::Wyhash11::hash(0, self.slice),
)
}
#[inline]
pub fn value(self) -> String {
debug_assert!(
(self.buf.as_ptr() as usize) <= (self.slice.as_ptr() as usize)
&& ((self.slice.as_ptr() as usize) + self.slice.len())
<= ((self.buf.as_ptr() as usize) + self.buf.len())
);
String::init(self.buf, self.slice)
}
#[inline]
pub fn sub(self, input: &'a [u8]) -> SlicedString<'a> {
if cfg!(debug_assertions) {
if !bun_alloc::is_slice_in_buffer(input, self.buf) {
let start_buf = self.buf.as_ptr() as usize;
let end_buf = (self.buf.as_ptr() as usize) + self.buf.len();
let start_i = input.as_ptr() as usize;
let end_i = (input.as_ptr() as usize) + input.len();
bun_core::Output::panic(format_args!(
concat!(
"SlicedString.sub input [{}, {}) is not a substring of the ",
"slice [{}, {})"
),
start_i, end_i, start_buf, end_buf
));
}
}
SlicedString {
buf: self.buf,
slice: input,
}
}
}
}
pub mod external_string {
use core::cmp::Ordering;
use super::semver_string::{Formatter, String};
#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct ExternalString {
pub value: String,
pub hash: u64,
}
impl ExternalString {
#[inline]
pub fn fmt<'a>(&'a self, buf: &'a [u8]) -> Formatter<'a> {
self.value.fmt(buf)
}
pub fn order(&self, rhs: &ExternalString, lhs_buf: &[u8], rhs_buf: &[u8]) -> Ordering {
if self.hash == rhs.hash && self.hash > 0 {
return Ordering::Equal;
}
self.value.order(rhs.value, lhs_buf, rhs_buf)
}
#[inline]
pub fn from(in_: &[u8]) -> ExternalString {
ExternalString {
value: String::init(in_, in_),
hash: bun_wyhash::hash(in_),
}
}
#[inline]
pub fn is_inline(&self) -> bool {
self.value.is_inline()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.value.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.value.len()
}
#[inline]
pub fn init(buf: &[u8], in_: &[u8], hash: u64) -> ExternalString {
ExternalString {
value: String::init(buf, in_),
hash,
}
}
#[inline]
pub fn slice<'a>(&'a self, buf: &'a [u8]) -> &'a [u8] {
self.value.slice(buf)
}
}
}
pub mod semver_string {
use core::cmp::Ordering;
use core::fmt;
use bun_alloc::AllocError;
use bun_collections::HashMap;
use bun_core::strings;
use super::external_string::ExternalString;
use super::sliced_string::SlicedString;
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Eq, Default)]
pub struct String {
pub bytes: [u8; String::MAX_INLINE_LEN],
}
impl fmt::Debug for String {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("String")
.field("bytes", &self.bytes)
.finish()
}
}
const MAX_ADDRESSABLE_SPACE_MASK: u64 = (1u64 << 63) - 1;
const _: () = assert!(
core::mem::size_of::<usize>() == 8,
"This code needs to be updated for non-64-bit architectures",
);
impl String {
pub const MAX_INLINE_LEN: usize = 8;
pub const EMPTY: String = String {
bytes: [0, 0, 0, 0, 0, 0, 0, 0],
};
pub fn from(inlinable_buffer: &'static [u8]) -> String {
debug_assert!(
!(inlinable_buffer.len() > Self::MAX_INLINE_LEN
|| (inlinable_buffer.len() == Self::MAX_INLINE_LEN
&& inlinable_buffer[Self::MAX_INLINE_LEN - 1] >= 0x80)),
"string constant too long to be inlined",
);
String::init(inlinable_buffer, inlinable_buffer)
}
#[inline]
pub fn fmt<'a>(&'a self, buf: &'a [u8]) -> Formatter<'a> {
Formatter { buf, str: self }
}
#[inline]
pub fn fmt_json<'a>(
&'a self,
buf: &'a [u8],
opts: JsonFormatterOptions,
) -> JsonFormatter<'a> {
JsonFormatter {
buf,
str: self,
opts,
}
}
#[inline]
pub fn fmt_store_path<'a>(&'a self, buf: &'a [u8]) -> StorePathFormatter<'a> {
StorePathFormatter { buf, str: self }
}
#[inline]
pub fn order(self, rhs: String, lhs_buf: &[u8], rhs_buf: &[u8]) -> Ordering {
strings::order(self.slice(lhs_buf), rhs.slice(rhs_buf))
}
#[inline]
pub fn can_inline(buf: &[u8]) -> bool {
const MAX_INLINE_LEN_M1: usize = String::MAX_INLINE_LEN - 1;
match buf.len() {
0..=MAX_INLINE_LEN_M1 => true,
Self::MAX_INLINE_LEN => buf[Self::MAX_INLINE_LEN - 1] & 0x80 == 0,
_ => false,
}
}
#[inline]
pub fn is_inline(self) -> bool {
self.bytes[Self::MAX_INLINE_LEN - 1] & 0x80 == 0
}
#[inline]
pub fn sliced<'a>(&'a self, buf: &'a [u8]) -> SlicedString<'a> {
if self.is_inline() {
let s = self.slice(b"");
SlicedString::init(s, s)
} else {
SlicedString::init(buf, self.slice(buf))
}
}
pub fn init(buf: &[u8], in_: &[u8]) -> String {
match in_.len() {
0 => String::default(),
1 => String {
bytes: [in_[0], 0, 0, 0, 0, 0, 0, 0],
},
2 => String {
bytes: [in_[0], in_[1], 0, 0, 0, 0, 0, 0],
},
3 => String {
bytes: [in_[0], in_[1], in_[2], 0, 0, 0, 0, 0],
},
4 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], 0, 0, 0, 0],
},
5 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], 0, 0, 0],
},
6 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], 0, 0],
},
7 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], in_[6], 0],
},
Self::MAX_INLINE_LEN => {
if in_[Self::MAX_INLINE_LEN - 1] >= 128 {
let ptr_bits: u64 = Pointer::init(buf, in_).to_bits();
let packed: u64 = (ptr_bits & MAX_ADDRESSABLE_SPACE_MASK) | (1u64 << 63);
String {
bytes: packed.to_ne_bytes(),
}
} else {
String {
bytes: [
in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], in_[6], in_[7],
],
}
}
}
_ => {
let ptr_bits: u64 = Pointer::init(buf, in_).to_bits();
let packed: u64 = (ptr_bits & MAX_ADDRESSABLE_SPACE_MASK) | (1u64 << 63);
String {
bytes: packed.to_ne_bytes(),
}
}
}
}
pub fn init_inline(in_: &[u8]) -> String {
debug_assert!(Self::can_inline(in_));
match in_.len() {
0 => String::default(),
1 => String {
bytes: [in_[0], 0, 0, 0, 0, 0, 0, 0],
},
2 => String {
bytes: [in_[0], in_[1], 0, 0, 0, 0, 0, 0],
},
3 => String {
bytes: [in_[0], in_[1], in_[2], 0, 0, 0, 0, 0],
},
4 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], 0, 0, 0, 0],
},
5 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], 0, 0, 0],
},
6 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], 0, 0],
},
7 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], in_[6], 0],
},
8 => String {
bytes: [
in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], in_[6], in_[7],
],
},
_ => unreachable!(),
}
}
pub fn init_append_if_needed(buf: &mut Vec<u8>, in_: &[u8]) -> Result<String, AllocError> {
Ok(match in_.len() {
0 => String::default(),
1 => String {
bytes: [in_[0], 0, 0, 0, 0, 0, 0, 0],
},
2 => String {
bytes: [in_[0], in_[1], 0, 0, 0, 0, 0, 0],
},
3 => String {
bytes: [in_[0], in_[1], in_[2], 0, 0, 0, 0, 0],
},
4 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], 0, 0, 0, 0],
},
5 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], 0, 0, 0],
},
6 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], 0, 0],
},
7 => String {
bytes: [in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], in_[6], 0],
},
Self::MAX_INLINE_LEN => {
if in_[Self::MAX_INLINE_LEN - 1] >= 128 {
Self::init_append(buf, in_)?
} else {
String {
bytes: [
in_[0], in_[1], in_[2], in_[3], in_[4], in_[5], in_[6], in_[7],
],
}
}
}
_ => Self::init_append(buf, in_)?,
})
}
pub fn init_append(buf: &mut Vec<u8>, in_: &[u8]) -> Result<String, AllocError> {
buf.extend_from_slice(in_);
let items = buf.as_slice();
let in_buf = &items[items.len() - in_.len()..];
let ptr_bits: u64 = Pointer::init(items, in_buf).to_bits();
let packed: u64 = (ptr_bits & MAX_ADDRESSABLE_SPACE_MASK) | (1u64 << 63);
Ok(String {
bytes: packed.to_ne_bytes(),
})
}
#[inline]
pub fn eql(self, that: String, this_buf: &[u8], that_buf: &[u8]) -> bool {
if self.is_inline() && that.is_inline() {
u64::from_ne_bytes(self.bytes) == u64::from_ne_bytes(that.bytes)
} else if self.is_inline() != that.is_inline() {
false
} else {
let a = self.ptr();
let b = that.ptr();
let (a_off, a_len) = (a.off as usize, a.len as usize);
let (b_off, b_len) = (b.off as usize, b.len as usize);
match (
this_buf.get(a_off..a_off + a_len),
that_buf.get(b_off..b_off + b_len),
) {
(Some(a), Some(b)) => strings::eql(a, b),
_ => false,
}
}
}
#[inline]
pub fn is_empty(self) -> bool {
u64::from_ne_bytes(self.bytes) == 0u64
}
#[inline]
pub fn len(self) -> usize {
match self.bytes[Self::MAX_INLINE_LEN - 1] & 128 {
0 => {
match self.bytes[0] {
0 => 0,
_ => {
let mut i: usize = 0;
while i < self.bytes.len() {
if self.bytes[i] == 0 {
return i;
}
i += 1;
}
8
}
}
}
_ => {
let ptr_ = self.ptr();
ptr_.len as usize
}
}
}
#[inline]
pub fn ptr(self) -> Pointer {
let bits: u64 = u64::from_ne_bytes(self.bytes);
let masked: u64 = bits & MAX_ADDRESSABLE_SPACE_MASK;
Pointer::from_bits(masked)
}
#[inline]
pub fn slice<'a>(&'a self, buf: &'a [u8]) -> &'a [u8] {
match self.bytes[Self::MAX_INLINE_LEN - 1] & 128 {
0 => {
match self.bytes[0] {
0 => b"",
_ => {
let mut i: usize = 0;
while i < self.bytes.len() {
if self.bytes[i] == 0 {
return &self.bytes[0..i];
}
i += 1;
}
&self.bytes
}
}
}
_ => {
let ptr_ = self.ptr();
let (off, len) = (ptr_.off as usize, ptr_.len as usize);
buf.get(off..off + len).unwrap_or_default()
}
}
}
}
pub struct Buf<'a> {
pub bytes: &'a mut Vec<u8>,
pub pool: &'a mut StringPool,
}
impl<'a> Buf<'a> {
pub fn append(&mut self, str: &[u8]) -> Result<String, AllocError> {
if String::can_inline(str) {
return Ok(String::init_inline(str));
}
let hash = Builder::string_hash(str);
let entry = self.pool.get_or_put(hash)?;
if entry.found_existing {
return Ok(*entry.value_ptr);
}
let new = String::init_append(self.bytes, str)?;
*entry.value_ptr = new;
Ok(new)
}
pub fn append_with_hash(&mut self, str: &[u8], hash: u64) -> Result<String, AllocError> {
if String::can_inline(str) {
return Ok(String::init_inline(str));
}
let entry = self.pool.get_or_put(hash)?;
if entry.found_existing {
return Ok(*entry.value_ptr);
}
let new = String::init_append(self.bytes, str)?;
*entry.value_ptr = new;
Ok(new)
}
pub fn append_external(&mut self, str: &[u8]) -> Result<ExternalString, AllocError> {
let hash = Builder::string_hash(str);
if String::can_inline(str) {
return Ok(ExternalString {
value: String::init_inline(str),
hash,
});
}
let entry = self.pool.get_or_put(hash)?;
if entry.found_existing {
return Ok(ExternalString {
value: *entry.value_ptr,
hash,
});
}
let new = String::init_append(self.bytes, str)?;
*entry.value_ptr = new;
Ok(ExternalString { value: new, hash })
}
pub fn append_external_with_hash(
&mut self,
str: &[u8],
hash: u64,
) -> Result<ExternalString, AllocError> {
if String::can_inline(str) {
return Ok(ExternalString {
value: String::init_inline(str),
hash,
});
}
let entry = self.pool.get_or_put(hash)?;
if entry.found_existing {
return Ok(ExternalString {
value: *entry.value_ptr,
hash,
});
}
let new = String::init_append(self.bytes, str)?;
*entry.value_ptr = new;
Ok(ExternalString { value: new, hash })
}
}
pub enum Tag {
Small,
Big,
}
pub struct Formatter<'a> {
pub str: &'a String,
pub buf: &'a [u8],
}
impl<'a> fmt::Display for Formatter<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let str = self.str;
write!(f, "{}", bstr::BStr::new(str.slice(self.buf)))
}
}
#[derive(Copy, Clone)]
pub struct JsonFormatterOptions {
pub quote: bool,
}
impl Default for JsonFormatterOptions {
fn default() -> Self {
Self { quote: true }
}
}
pub struct JsonFormatter<'a> {
pub str: &'a String,
pub buf: &'a [u8],
pub opts: JsonFormatterOptions,
}
impl<'a> fmt::Display for JsonFormatter<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
bun_core::fmt::format_json_string_utf8(
self.str.slice(self.buf),
bun_core::fmt::JSONFormatterUTF8Options {
quote: self.opts.quote
},
),
)
}
}
pub struct StorePathFormatter<'a> {
pub str: &'a String,
pub buf: &'a [u8],
}
impl<'a> fmt::Display for StorePathFormatter<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for &c in self.str.slice(self.buf) {
let n = match c {
b'/' => b'+',
b'\\' => b'+',
b':' => b'+',
b'#' => b'+',
_ => c,
};
use core::fmt::Write;
f.write_char(n as char)?;
}
Ok(())
}
}
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum SortDirection {
Asc,
Desc,
}
pub struct Sorter<'a> {
pub direction: SortDirection,
pub lhs_buf: &'a [u8],
pub rhs_buf: &'a [u8],
}
impl<'a> Sorter<'a> {
pub fn less_than(&self, lhs: String, rhs: String) -> bool {
lhs.order(rhs, self.lhs_buf, self.rhs_buf)
== if self.direction == SortDirection::Asc {
Ordering::Less
} else {
Ordering::Greater
}
}
}
pub struct HashContext<'a> {
pub arg_buf: &'a [u8],
pub existing_buf: &'a [u8],
}
impl<'a> HashContext<'a> {
pub fn eql(&self, arg: String, existing: String) -> bool {
arg.eql(existing, self.arg_buf, self.existing_buf)
}
pub fn hash(&self, arg: String) -> u64 {
let str = arg.slice(self.arg_buf);
bun_wyhash::hash(str)
}
}
pub struct ArrayHashContext<'a> {
pub arg_buf: &'a [u8],
pub existing_buf: &'a [u8],
}
impl<'a> ArrayHashContext<'a> {
pub fn eql(&self, arg: String, existing: String, _: usize) -> bool {
arg.eql(existing, self.arg_buf, self.existing_buf)
}
pub fn hash(&self, arg: String) -> u32 {
let str = arg.slice(self.arg_buf);
bun_wyhash::hash(str) as u32
}
}
impl<'a> bun_collections::array_hash_map::ArrayHashAdapter<String, String>
for ArrayHashContext<'a>
{
#[inline]
fn hash(&self, key: &String) -> u32 {
ArrayHashContext::hash(self, *key)
}
#[inline]
fn eql(&self, a: &String, b: &String, b_index: usize) -> bool {
ArrayHashContext::eql(self, *a, *b, b_index)
}
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct Pointer {
pub off: u32,
pub len: u32,
}
impl Pointer {
#[inline]
pub fn init(buf: &[u8], in_: &[u8]) -> Pointer {
if cfg!(debug_assertions) {
debug_assert!(bun_alloc::is_slice_in_buffer(in_, buf));
}
Pointer {
off: (in_.as_ptr() as usize - buf.as_ptr() as usize) as u32,
len: in_.len() as u32,
}
}
#[inline]
pub fn to_bits(self) -> u64 {
let mut b = [0u8; 8];
b[..4].copy_from_slice(&self.off.to_ne_bytes());
b[4..].copy_from_slice(&self.len.to_ne_bytes());
u64::from_ne_bytes(b)
}
#[inline]
pub fn from_bits(bits: u64) -> Pointer {
let b = bits.to_ne_bytes();
Pointer {
off: u32::from_ne_bytes([b[0], b[1], b[2], b[3]]),
len: u32::from_ne_bytes([b[4], b[5], b[6], b[7]]),
}
}
}
pub trait BuilderStringType: Sized {
fn from_init(allocated: &[u8], slice_: &[u8], hash: u64) -> Self;
fn from_pooled(value: String, hash: u64) -> Self;
}
impl BuilderStringType for String {
fn from_init(allocated: &[u8], slice_: &[u8], _hash: u64) -> Self {
String::init(allocated, slice_)
}
fn from_pooled(value: String, _hash: u64) -> Self {
value
}
}
impl BuilderStringType for ExternalString {
fn from_init(allocated: &[u8], slice_: &[u8], hash: u64) -> Self {
ExternalString::init(allocated, slice_, hash)
}
fn from_pooled(value: String, hash: u64) -> Self {
ExternalString { value, hash }
}
}
#[derive(Default)]
pub struct StringPool {
map: HashMap<u64, String, bun_collections::IdentityContext<u64>>,
}
pub struct StringPoolEntry<'a> {
pub found_existing: bool,
pub value_ptr: &'a mut String,
}
impl StringPool {
pub fn get_or_put(&mut self, hash: u64) -> Result<StringPoolEntry<'_>, AllocError> {
let gpe = self.map.get_or_put(hash)?;
Ok(StringPoolEntry {
found_existing: gpe.found_existing,
value_ptr: gpe.value_ptr,
})
}
#[inline]
pub fn contains(&self, hash: u64) -> bool {
self.map.contains_key(&hash)
}
#[inline]
pub fn capacity(&self) -> usize {
self.map.capacity()
}
#[inline]
pub fn ensure_total_capacity(&mut self, n: usize) -> Result<(), AllocError> {
self.map.ensure_total_capacity(n)
}
}
#[derive(Default)]
pub struct Builder {
pub len: usize,
pub cap: usize,
pub ptr: Option<Box<[u8]>>,
pub string_pool: StringPool,
}
impl Builder {
#[inline]
pub fn string_hash(buf: &[u8]) -> u64 {
bun_wyhash::Wyhash11::hash(0, buf)
}
#[inline]
pub fn count(&mut self, slice_: &[u8]) {
self.count_with_hash(
slice_,
if slice_.len() >= String::MAX_INLINE_LEN {
Self::string_hash(slice_)
} else {
u64::MAX
},
)
}
#[inline]
pub fn count_with_hash(&mut self, slice_: &[u8], hash: u64) {
if slice_.len() <= String::MAX_INLINE_LEN {
return;
}
if !self.string_pool.contains(hash) {
self.cap += slice_.len();
}
}
#[inline]
pub fn allocated_slice(&self) -> &[u8] {
if self.cap > 0 {
&self.ptr.as_ref().expect("allocate() not called")[0..self.cap]
} else {
&[]
}
}
pub fn allocate(&mut self) -> Result<(), AllocError> {
let ptr_ = vec![0u8; self.cap].into_boxed_slice();
self.ptr = Some(ptr_);
Ok(())
}
pub fn append<T: BuilderStringType>(&mut self, slice_: &[u8]) -> T {
self.append_with_hash::<T>(slice_, Self::string_hash(slice_))
}
pub fn append_utf8_without_pool<T: BuilderStringType>(
&mut self,
slice_: &[u8],
hash: u64,
) -> T {
if slice_.len() <= String::MAX_INLINE_LEN {
if strings::is_all_ascii(slice_) {
return T::from_init(self.allocated_slice(), slice_, hash);
}
}
if cfg!(debug_assertions) {
debug_assert!(self.len <= self.cap); debug_assert!(self.ptr.is_some()); }
let start = self.len;
let end = self.cap;
{
let dst = &mut self.ptr.as_mut().unwrap()[start..end];
dst[..slice_.len()].copy_from_slice(slice_);
}
self.len += slice_.len();
if cfg!(debug_assertions) {
debug_assert!(self.len <= self.cap);
}
let allocated = &self.ptr.as_ref().unwrap()[0..self.cap];
let final_slice = &allocated[start..start + slice_.len()];
T::from_init(allocated, final_slice, hash)
}
pub fn append_without_pool<T: BuilderStringType>(&mut self, slice_: &[u8], hash: u64) -> T {
if slice_.len() <= String::MAX_INLINE_LEN {
return T::from_init(self.allocated_slice(), slice_, hash);
}
if cfg!(debug_assertions) {
debug_assert!(self.len <= self.cap); debug_assert!(self.ptr.is_some()); }
let start = self.len;
let end = self.cap;
{
let dst = &mut self.ptr.as_mut().unwrap()[start..end];
dst[..slice_.len()].copy_from_slice(slice_);
}
self.len += slice_.len();
if cfg!(debug_assertions) {
debug_assert!(self.len <= self.cap);
}
let allocated = &self.ptr.as_ref().unwrap()[0..self.cap];
let final_slice = &allocated[start..start + slice_.len()];
T::from_init(allocated, final_slice, hash)
}
pub fn append_with_hash<T: BuilderStringType>(&mut self, slice_: &[u8], hash: u64) -> T {
if slice_.len() <= String::MAX_INLINE_LEN {
return T::from_init(self.allocated_slice(), slice_, hash);
}
if cfg!(debug_assertions) {
debug_assert!(self.len <= self.cap); debug_assert!(self.ptr.is_some()); }
let start = self.len;
let cap = self.cap;
let string_entry = self.string_pool.get_or_put(hash).expect("unreachable");
if string_entry.found_existing {
let allocated = &self.ptr.as_ref().unwrap()[0..cap];
if !strings::eql(string_entry.value_ptr.slice(allocated), slice_) {
return self.append_without_pool::<T>(slice_, hash);
}
} else {
{
let dst = &mut self.ptr.as_mut().unwrap()[start..cap];
dst[..slice_.len()].copy_from_slice(slice_);
}
self.len += slice_.len();
let allocated = &self.ptr.as_ref().unwrap()[0..cap];
let final_slice = &allocated[start..start + slice_.len()];
*string_entry.value_ptr = String::init(allocated, final_slice);
}
if cfg!(debug_assertions) {
debug_assert!(self.len <= self.cap);
}
T::from_pooled(*string_entry.value_ptr, hash)
}
}
const _: () = assert!(
core::mem::size_of::<String>() == core::mem::size_of::<Pointer>(),
"String types must be the same size",
);
}