2020-05-05 06:24:13 +02:00
|
|
|
//! Module containing various utility types and functions.
|
2020-05-14 12:27:22 +02:00
|
|
|
|
2020-05-26 08:14:03 +02:00
|
|
|
use crate::fn_native::{shared_make_mut, shared_take, Shared};
|
|
|
|
|
2020-05-05 06:24:13 +02:00
|
|
|
use crate::stdlib::{
|
|
|
|
any::TypeId,
|
2020-05-26 08:14:03 +02:00
|
|
|
borrow::Borrow,
|
2020-05-26 17:05:44 +02:00
|
|
|
boxed::Box,
|
2020-07-30 07:28:25 +02:00
|
|
|
cmp::Ordering,
|
2020-05-05 09:00:10 +02:00
|
|
|
fmt,
|
2020-05-30 18:02:23 +02:00
|
|
|
hash::{BuildHasher, Hash, Hasher},
|
2020-10-28 15:18:44 +01:00
|
|
|
iter::{empty, FromIterator},
|
2020-07-29 10:10:06 +02:00
|
|
|
ops::{Add, AddAssign, Deref},
|
2020-05-26 08:14:03 +02:00
|
|
|
str::FromStr,
|
2020-05-26 17:05:44 +02:00
|
|
|
string::{String, ToString},
|
2020-05-05 06:24:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_std"))]
|
2020-05-10 15:25:47 +02:00
|
|
|
use crate::stdlib::collections::hash_map::DefaultHasher;
|
2020-05-05 06:24:13 +02:00
|
|
|
|
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use ahash::AHasher;
|
|
|
|
|
2020-05-30 18:02:23 +02:00
|
|
|
/// A hasher that only takes one single `u64` and returns it as a hash key.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics when hashing any data type other than a `u64`.
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
|
|
|
|
pub struct StraightHasher(u64);
|
|
|
|
|
|
|
|
impl Hasher for StraightHasher {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-30 18:02:23 +02:00
|
|
|
fn finish(&self) -> u64 {
|
|
|
|
self.0
|
|
|
|
}
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-30 18:02:23 +02:00
|
|
|
fn write(&mut self, bytes: &[u8]) {
|
|
|
|
let mut key = [0_u8; 8];
|
|
|
|
key.copy_from_slice(&bytes[..8]); // Panics if fewer than 8 bytes
|
|
|
|
self.0 = u64::from_le_bytes(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A hash builder for `StraightHasher`.
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
|
|
|
|
pub struct StraightHasherBuilder;
|
|
|
|
|
|
|
|
impl BuildHasher for StraightHasherBuilder {
|
|
|
|
type Hasher = StraightHasher;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-30 18:02:23 +02:00
|
|
|
fn build_hasher(&self) -> Self::Hasher {
|
2020-10-29 04:37:51 +01:00
|
|
|
Default::default()
|
2020-05-30 18:02:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-03 12:49:11 +02:00
|
|
|
/// _[INTERNALS]_ Calculate a `u64` hash key from a module-qualified function name and parameter types.
|
2020-09-29 07:06:48 +02:00
|
|
|
/// Exported under the `internals` feature only.
|
2020-05-05 06:24:13 +02:00
|
|
|
///
|
2020-05-07 18:19:08 +02:00
|
|
|
/// Module names are passed in via `&str` references from an iterator.
|
|
|
|
/// Parameter types are passed in via `TypeId` values from an iterator.
|
|
|
|
///
|
2020-05-10 15:25:47 +02:00
|
|
|
/// # Note
|
2020-05-07 18:19:08 +02:00
|
|
|
///
|
|
|
|
/// The first module name is skipped. Hashing starts from the _second_ module in the chain.
|
2020-10-28 15:18:44 +01:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn calc_native_fn_hash<'a>(
|
|
|
|
modules: impl Iterator<Item = &'a str>,
|
|
|
|
fn_name: &str,
|
|
|
|
params: impl Iterator<Item = TypeId>,
|
|
|
|
) -> u64 {
|
|
|
|
calc_fn_hash(modules, fn_name, None, params)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// _[INTERNALS]_ Calculate a `u64` hash key from a module-qualified function name and the number of parameters,
|
|
|
|
/// but no parameter types.
|
|
|
|
/// Exported under the `internals` feature only.
|
|
|
|
///
|
|
|
|
/// Module names are passed in via `&str` references from an iterator.
|
|
|
|
/// Parameter types are passed in via `TypeId` values from an iterator.
|
|
|
|
///
|
|
|
|
/// # Note
|
|
|
|
///
|
|
|
|
/// The first module name is skipped. Hashing starts from the _second_ module in the chain.
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn calc_script_fn_hash<'a>(
|
2020-05-07 18:19:08 +02:00
|
|
|
modules: impl Iterator<Item = &'a str>,
|
|
|
|
fn_name: &str,
|
2020-05-19 14:07:51 +02:00
|
|
|
num: usize,
|
2020-10-28 15:18:44 +01:00
|
|
|
) -> u64 {
|
|
|
|
calc_fn_hash(modules, fn_name, Some(num), empty())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculate a `u64` hash key from a module-qualified function name and parameter types.
|
|
|
|
///
|
|
|
|
/// Module names are passed in via `&str` references from an iterator.
|
|
|
|
/// Parameter types are passed in via `TypeId` values from an iterator.
|
|
|
|
///
|
|
|
|
/// # Note
|
|
|
|
///
|
|
|
|
/// The first module name is skipped. Hashing starts from the _second_ module in the chain.
|
|
|
|
fn calc_fn_hash<'a>(
|
|
|
|
modules: impl Iterator<Item = &'a str>,
|
|
|
|
fn_name: &str,
|
|
|
|
num: Option<usize>,
|
2020-05-07 18:19:08 +02:00
|
|
|
params: impl Iterator<Item = TypeId>,
|
|
|
|
) -> u64 {
|
2020-05-05 06:24:13 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
2020-10-28 15:18:44 +01:00
|
|
|
let s: &mut AHasher = &mut Default::default();
|
2020-05-05 06:24:13 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2020-10-28 15:18:44 +01:00
|
|
|
let s = &mut DefaultHasher::new();
|
2020-05-05 06:24:13 +02:00
|
|
|
|
2020-05-07 18:19:08 +02:00
|
|
|
// We always skip the first module
|
2020-10-28 15:18:44 +01:00
|
|
|
modules.skip(1).for_each(|m| m.hash(s));
|
2020-05-05 06:24:13 +02:00
|
|
|
s.write(fn_name.as_bytes());
|
2020-10-28 15:30:29 +01:00
|
|
|
if let Some(num) = num {
|
|
|
|
s.write_usize(num);
|
2020-10-28 15:18:44 +01:00
|
|
|
} else {
|
2020-10-28 15:30:29 +01:00
|
|
|
params.for_each(|t| t.hash(s));
|
|
|
|
}
|
2020-05-05 06:24:13 +02:00
|
|
|
s.finish()
|
|
|
|
}
|
|
|
|
|
2020-05-26 08:14:03 +02:00
|
|
|
/// The system immutable string type.
|
|
|
|
///
|
|
|
|
/// An `ImmutableString` wraps an `Rc<String>` (or `Arc<String>` under the `sync` feature)
|
|
|
|
/// so that it can be simply shared and not cloned.
|
|
|
|
///
|
2020-10-27 04:30:38 +01:00
|
|
|
/// # Example
|
2020-05-26 08:14:03 +02:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use rhai::ImmutableString;
|
|
|
|
///
|
|
|
|
/// let s1: ImmutableString = "hello".into();
|
|
|
|
///
|
|
|
|
/// // No actual cloning of the string is involved below.
|
|
|
|
/// let s2 = s1.clone();
|
|
|
|
/// let s3 = s2.clone();
|
|
|
|
///
|
|
|
|
/// assert_eq!(s1, s2);
|
|
|
|
///
|
|
|
|
/// // Clones the underlying string (because it is already shared) and extracts it.
|
|
|
|
/// let mut s: String = s1.into_owned();
|
|
|
|
///
|
|
|
|
/// // Changing the clone has no impact on the previously shared version.
|
|
|
|
/// s.push_str(", world!");
|
|
|
|
///
|
|
|
|
/// // The old version still exists.
|
|
|
|
/// assert_eq!(s2, s3);
|
|
|
|
/// assert_eq!(s2.as_str(), "hello");
|
|
|
|
///
|
|
|
|
/// // Not equals!
|
|
|
|
/// assert_ne!(s2.as_str(), s.as_str());
|
|
|
|
/// assert_eq!(s, "hello, world!");
|
|
|
|
/// ```
|
|
|
|
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
|
|
|
|
pub struct ImmutableString(Shared<String>);
|
|
|
|
|
|
|
|
impl Deref for ImmutableString {
|
|
|
|
type Target = String;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsRef<String> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn as_ref(&self) -> &String {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-30 07:28:25 +02:00
|
|
|
impl Borrow<String> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-07-30 07:28:25 +02:00
|
|
|
fn borrow(&self) -> &String {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-26 08:14:03 +02:00
|
|
|
impl Borrow<str> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn borrow(&self) -> &str {
|
|
|
|
self.0.as_str()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&str> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from(value: &str) -> Self {
|
|
|
|
Self(value.to_string().into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl From<String> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from(value: String) -> Self {
|
|
|
|
Self(value.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Box<String>> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from(value: Box<String>) -> Self {
|
|
|
|
Self(value.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ImmutableString> for String {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from(value: ImmutableString) -> Self {
|
|
|
|
value.into_owned()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for ImmutableString {
|
|
|
|
type Err = ();
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
Ok(Self(s.to_string().into()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromIterator<char> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
|
|
|
|
Self(iter.into_iter().collect::<String>().into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> FromIterator<&'a char> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
|
|
|
|
Self(iter.into_iter().cloned().collect::<String>().into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> FromIterator<&'a str> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
|
|
|
|
Self(iter.into_iter().collect::<String>().into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> FromIterator<String> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
|
|
|
|
Self(iter.into_iter().collect::<String>().into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
fmt::Display::fmt(self.0.as_str(), f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
fmt::Debug::fmt(self.0.as_str(), f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Add for ImmutableString {
|
|
|
|
type Output = Self;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add(mut self, rhs: Self) -> Self::Output {
|
|
|
|
if rhs.is_empty() {
|
|
|
|
self
|
|
|
|
} else if self.is_empty() {
|
|
|
|
rhs
|
|
|
|
} else {
|
|
|
|
self.make_mut().push_str(rhs.0.as_str());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Add for &ImmutableString {
|
|
|
|
type Output = ImmutableString;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
|
|
if rhs.is_empty() {
|
|
|
|
self.clone()
|
|
|
|
} else if self.is_empty() {
|
|
|
|
rhs.clone()
|
|
|
|
} else {
|
|
|
|
let mut s = self.clone();
|
|
|
|
s.make_mut().push_str(rhs.0.as_str());
|
|
|
|
s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AddAssign<&ImmutableString> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add_assign(&mut self, rhs: &ImmutableString) {
|
|
|
|
if !rhs.is_empty() {
|
|
|
|
if self.is_empty() {
|
|
|
|
self.0 = rhs.0.clone();
|
|
|
|
} else {
|
|
|
|
self.make_mut().push_str(rhs.0.as_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-01 16:28:13 +02:00
|
|
|
impl AddAssign<ImmutableString> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline]
|
2020-08-01 16:28:13 +02:00
|
|
|
fn add_assign(&mut self, rhs: ImmutableString) {
|
|
|
|
if !rhs.is_empty() {
|
|
|
|
if self.is_empty() {
|
|
|
|
self.0 = rhs.0;
|
|
|
|
} else {
|
|
|
|
self.make_mut().push_str(rhs.0.as_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-26 08:14:03 +02:00
|
|
|
impl Add<&str> for ImmutableString {
|
|
|
|
type Output = Self;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add(mut self, rhs: &str) -> Self::Output {
|
|
|
|
if rhs.is_empty() {
|
|
|
|
self
|
|
|
|
} else {
|
|
|
|
self.make_mut().push_str(rhs);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Add<&str> for &ImmutableString {
|
|
|
|
type Output = ImmutableString;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add(self, rhs: &str) -> Self::Output {
|
|
|
|
if rhs.is_empty() {
|
|
|
|
self.clone()
|
|
|
|
} else {
|
|
|
|
let mut s = self.clone();
|
|
|
|
s.make_mut().push_str(rhs);
|
|
|
|
s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AddAssign<&str> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add_assign(&mut self, rhs: &str) {
|
|
|
|
if !rhs.is_empty() {
|
|
|
|
self.make_mut().push_str(rhs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Add<String> for ImmutableString {
|
|
|
|
type Output = Self;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add(mut self, rhs: String) -> Self::Output {
|
|
|
|
if rhs.is_empty() {
|
|
|
|
self
|
|
|
|
} else if self.is_empty() {
|
|
|
|
rhs.into()
|
|
|
|
} else {
|
|
|
|
self.make_mut().push_str(&rhs);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Add<String> for &ImmutableString {
|
|
|
|
type Output = ImmutableString;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add(self, rhs: String) -> Self::Output {
|
|
|
|
if rhs.is_empty() {
|
|
|
|
self.clone()
|
|
|
|
} else if self.is_empty() {
|
|
|
|
rhs.into()
|
|
|
|
} else {
|
|
|
|
let mut s = self.clone();
|
|
|
|
s.make_mut().push_str(&rhs);
|
|
|
|
s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Add<char> for ImmutableString {
|
|
|
|
type Output = Self;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add(mut self, rhs: char) -> Self::Output {
|
|
|
|
self.make_mut().push(rhs);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Add<char> for &ImmutableString {
|
|
|
|
type Output = ImmutableString;
|
|
|
|
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add(self, rhs: char) -> Self::Output {
|
|
|
|
let mut s = self.clone();
|
|
|
|
s.make_mut().push(rhs);
|
|
|
|
s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AddAssign<char> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
fn add_assign(&mut self, rhs: char) {
|
|
|
|
self.make_mut().push(rhs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-30 07:28:25 +02:00
|
|
|
impl<S: AsRef<str>> PartialEq<S> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-07-30 07:28:25 +02:00
|
|
|
fn eq(&self, other: &S) -> bool {
|
|
|
|
self.as_str().eq(other.as_ref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<ImmutableString> for str {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-07-30 07:28:25 +02:00
|
|
|
fn eq(&self, other: &ImmutableString) -> bool {
|
|
|
|
self.eq(other.as_str())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<ImmutableString> for String {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-07-30 07:28:25 +02:00
|
|
|
fn eq(&self, other: &ImmutableString) -> bool {
|
|
|
|
self.eq(other.as_str())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: AsRef<str>> PartialOrd<S> for ImmutableString {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-07-30 07:28:25 +02:00
|
|
|
fn partial_cmp(&self, other: &S) -> Option<Ordering> {
|
|
|
|
self.as_str().partial_cmp(other.as_ref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd<ImmutableString> for str {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-07-30 07:28:25 +02:00
|
|
|
fn partial_cmp(&self, other: &ImmutableString) -> Option<Ordering> {
|
|
|
|
self.partial_cmp(other.as_str())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd<ImmutableString> for String {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-07-30 07:28:25 +02:00
|
|
|
fn partial_cmp(&self, other: &ImmutableString) -> Option<Ordering> {
|
|
|
|
self.as_str().partial_cmp(other.as_str())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-26 08:14:03 +02:00
|
|
|
impl ImmutableString {
|
|
|
|
/// Consume the `ImmutableString` and convert it into a `String`.
|
|
|
|
/// If there are other references to the same string, a cloned copy is returned.
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
pub fn into_owned(mut self) -> String {
|
|
|
|
self.make_mut(); // Make sure it is unique reference
|
|
|
|
shared_take(self.0) // Should succeed
|
|
|
|
}
|
|
|
|
/// Make sure that the `ImmutableString` is unique (i.e. no other outstanding references).
|
|
|
|
/// Then return a mutable reference to the `String`.
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-05-26 08:14:03 +02:00
|
|
|
pub fn make_mut(&mut self) -> &mut String {
|
|
|
|
shared_make_mut(&mut self.0)
|
|
|
|
}
|
|
|
|
}
|