2020-07-12 22:16:48 +00:00
|
|
|
use gc_arena::{Collect, Gc, MutationContext};
|
2020-07-14 02:09:34 +00:00
|
|
|
use std::cmp::{Eq, Ord, Ordering, PartialOrd};
|
2020-07-12 23:29:04 +00:00
|
|
|
use std::fmt;
|
2020-07-14 02:09:34 +00:00
|
|
|
use std::hash::{Hash, Hasher};
|
2020-07-12 22:16:48 +00:00
|
|
|
use std::ops::Deref;
|
|
|
|
|
2020-07-22 19:55:49 +00:00
|
|
|
#[derive(Clone, Copy, Collect)]
|
2020-07-12 22:16:48 +00:00
|
|
|
#[collect(no_drop)]
|
2020-07-12 22:43:12 +00:00
|
|
|
enum Source<'gc> {
|
|
|
|
Owned(Gc<'gc, String>),
|
|
|
|
Static(&'static str),
|
|
|
|
}
|
|
|
|
|
2020-07-22 19:55:49 +00:00
|
|
|
impl fmt::Debug for Source<'_> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
Source::Owned(str) => f.debug_tuple("Owned").field(str.deref()).finish(),
|
|
|
|
Source::Static(str) => f.debug_tuple("Static").field(str).finish(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-14 02:09:34 +00:00
|
|
|
#[derive(Debug, Clone, Copy, Collect)]
|
2020-07-12 22:43:12 +00:00
|
|
|
#[collect(no_drop)]
|
2020-07-13 10:09:30 +00:00
|
|
|
pub struct AvmString<'gc> {
|
2020-07-12 22:43:12 +00:00
|
|
|
source: Source<'gc>,
|
|
|
|
}
|
2020-07-12 22:16:48 +00:00
|
|
|
|
2020-07-13 10:09:30 +00:00
|
|
|
impl<'gc> AvmString<'gc> {
|
2020-07-12 22:16:48 +00:00
|
|
|
pub fn new<S: Into<String>>(gc_context: MutationContext<'gc, '_>, string: S) -> Self {
|
2020-07-12 22:43:12 +00:00
|
|
|
Self {
|
|
|
|
source: Source::Owned(Gc::allocate(gc_context, string.into())),
|
|
|
|
}
|
2020-07-12 22:16:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_str(&self) -> &str {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-13 10:09:30 +00:00
|
|
|
impl Default for AvmString<'_> {
|
2020-07-12 23:29:04 +00:00
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
source: Source::Static(""),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-13 10:09:30 +00:00
|
|
|
impl<'gc> From<&'static str> for AvmString<'gc> {
|
2020-07-12 22:43:12 +00:00
|
|
|
fn from(str: &'static str) -> Self {
|
|
|
|
Self {
|
|
|
|
source: Source::Static(str),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-13 10:09:30 +00:00
|
|
|
impl fmt::Display for AvmString<'_> {
|
2020-07-12 23:29:04 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.write_str(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-13 10:09:30 +00:00
|
|
|
impl Deref for AvmString<'_> {
|
2020-07-12 22:16:48 +00:00
|
|
|
type Target = str;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn deref(&self) -> &str {
|
2020-07-12 22:43:12 +00:00
|
|
|
match &self.source {
|
|
|
|
Source::Owned(str) => str.deref(),
|
|
|
|
Source::Static(str) => str,
|
|
|
|
}
|
2020-07-12 22:16:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-13 10:09:30 +00:00
|
|
|
impl AsRef<str> for AvmString<'_> {
|
2020-07-12 22:16:48 +00:00
|
|
|
#[inline]
|
|
|
|
fn as_ref(&self) -> &str {
|
2020-07-12 22:43:12 +00:00
|
|
|
match &self.source {
|
|
|
|
Source::Owned(str) => str,
|
|
|
|
Source::Static(str) => str,
|
|
|
|
}
|
2020-07-12 22:16:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-13 10:09:30 +00:00
|
|
|
impl<'gc> PartialEq<AvmString<'gc>> for AvmString<'gc> {
|
2020-07-12 23:29:04 +00:00
|
|
|
#[inline]
|
2020-07-13 10:09:30 +00:00
|
|
|
fn eq(&self, other: &AvmString<'gc>) -> bool {
|
2020-07-12 23:29:04 +00:00
|
|
|
PartialEq::eq(self.as_str(), other.as_str())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-14 02:09:34 +00:00
|
|
|
impl<'gc> Eq for AvmString<'gc> {}
|
|
|
|
|
|
|
|
impl<'gc> PartialOrd<AvmString<'gc>> for AvmString<'gc> {
|
|
|
|
fn partial_cmp(&self, other: &AvmString<'gc>) -> Option<Ordering> {
|
|
|
|
self.as_ref().partial_cmp(other.as_ref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'gc> Ord for AvmString<'gc> {
|
|
|
|
fn cmp(&self, other: &AvmString<'gc>) -> Ordering {
|
|
|
|
self.as_ref().cmp(other.as_ref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'gc> Hash for AvmString<'gc> {
|
|
|
|
fn hash<H>(&self, state: &mut H)
|
|
|
|
where
|
|
|
|
H: Hasher,
|
|
|
|
{
|
|
|
|
self.as_ref().hash(state)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-12 22:16:48 +00:00
|
|
|
macro_rules! impl_eq {
|
|
|
|
($lhs:ty, $rhs: ty) => {
|
2021-02-12 13:03:17 +00:00
|
|
|
#[allow(unused_lifetimes, clippy::redundant_slicing)]
|
2020-07-12 22:16:48 +00:00
|
|
|
impl<'a, 'b> PartialEq<$rhs> for $lhs {
|
|
|
|
#[inline]
|
|
|
|
fn eq(&self, other: &$rhs) -> bool {
|
|
|
|
PartialEq::eq(&self[..], &other[..])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-12 13:03:17 +00:00
|
|
|
#[allow(unused_lifetimes, clippy::redundant_slicing)]
|
2020-07-12 22:16:48 +00:00
|
|
|
impl<'a, 'b> PartialEq<$lhs> for $rhs {
|
|
|
|
#[inline]
|
|
|
|
fn eq(&self, other: &$lhs) -> bool {
|
|
|
|
PartialEq::eq(&self[..], &other[..])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-07-13 10:09:30 +00:00
|
|
|
impl_eq! { AvmString<'_>, str }
|
|
|
|
impl_eq! { AvmString<'_>, &'a str }
|
|
|
|
impl_eq! { AvmString<'_>, String }
|