Skip to content

Commit 4f9c106

Browse files
committed
refactor: split
1 parent 886e3e5 commit 4f9c106

File tree

3 files changed

+280
-253
lines changed

3 files changed

+280
-253
lines changed

crates/hstr/src/lib.rs

Lines changed: 8 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,23 @@ use std::{
1313

1414
use debug_unreachable::debug_unreachable;
1515
use once_cell::sync::Lazy;
16-
use wtf8::Wtf8;
1716

1817
pub use crate::dynamic::{global_atom_store_gc, AtomStore};
19-
use crate::tagged_value::TaggedValue;
18+
use crate::{
19+
macros::{get_hash, impl_from_alias, partial_eq},
20+
tagged_value::TaggedValue,
21+
};
2022

2123
mod dynamic;
2224
mod global_store;
25+
mod macros;
2326
mod tagged_value;
2427
#[cfg(test)]
2528
mod tests;
2629
pub mod wtf8;
30+
mod wtf8_atom;
31+
32+
pub use wtf8_atom::Wtf8Atom;
2733

2834
/// An immutable string which is cheap to clone, compare, hash, and has small
2935
/// size.
@@ -253,25 +259,6 @@ impl Atom {
253259
}
254260
}
255261

256-
macro_rules! get_hash {
257-
($self:expr) => {
258-
match $self.tag() {
259-
DYNAMIC_TAG => {
260-
unsafe { crate::dynamic::deref_from($self.unsafe_data) }
261-
.header
262-
.header
263-
.hash
264-
}
265-
INLINE_TAG => {
266-
// This is passed as input to the caller's `Hasher` implementation, so it's okay
267-
// that this isn't really a hash
268-
$self.unsafe_data.hash()
269-
}
270-
_ => unsafe { debug_unreachable!() },
271-
}
272-
};
273-
}
274-
275262
impl Atom {
276263
fn get_hash(&self) -> u64 {
277264
get_hash!(self)
@@ -307,35 +294,6 @@ impl Atom {
307294
}
308295
}
309296

310-
macro_rules! partial_eq {
311-
($self:expr, $other:expr) => {
312-
if $self.unsafe_data == $other.unsafe_data {
313-
return true;
314-
}
315-
316-
// If one is inline and the other is not, the length is different.
317-
// If one is static and the other is not, it's different.
318-
if $self.tag() != $other.tag() {
319-
return false;
320-
}
321-
322-
if $self.is_dynamic() && $other.is_dynamic() {
323-
let te = unsafe { crate::dynamic::deref_from($self.unsafe_data) };
324-
let oe = unsafe { crate::dynamic::deref_from($other.unsafe_data) };
325-
326-
if te.header.header.hash != oe.header.header.hash {
327-
return false;
328-
}
329-
330-
return te.slice == oe.slice;
331-
}
332-
333-
if $self.get_hash() != $other.get_hash() {
334-
return false;
335-
}
336-
};
337-
}
338-
339297
impl PartialEq for Atom {
340298
#[inline(never)]
341299
fn eq(&self, other: &Self) -> bool {
@@ -372,25 +330,6 @@ impl Clone for Atom {
372330
}
373331
}
374332

375-
macro_rules! impl_from_alias {
376-
($ty:ty) => {
377-
impl $ty {
378-
#[inline]
379-
pub(crate) fn from_alias(alias: TaggedValue) -> Self {
380-
if alias.tag() & TAG_MASK == DYNAMIC_TAG {
381-
unsafe {
382-
let arc = crate::dynamic::restore_arc(alias);
383-
forget(arc.clone());
384-
forget(arc);
385-
}
386-
}
387-
388-
Self { unsafe_data: alias }
389-
}
390-
}
391-
};
392-
}
393-
394333
impl_from_alias!(Atom);
395334

396335
impl Deref for Atom {
@@ -485,190 +424,6 @@ impl Atom {
485424
}
486425
}
487426

488-
/// A WTF-8 encoded atom. This is like [Atom], but can contain unpaired
489-
/// surrogates.
490-
pub struct Wtf8Atom {
491-
unsafe_data: TaggedValue,
492-
}
493-
494-
impl Wtf8Atom {
495-
#[inline(always)]
496-
pub fn new<S>(s: S) -> Self
497-
where
498-
Self: From<S>,
499-
{
500-
Self::from(s)
501-
}
502-
503-
#[inline(always)]
504-
fn tag(&self) -> u8 {
505-
self.unsafe_data.tag() & TAG_MASK
506-
}
507-
508-
/// Return true if this is a dynamic Atom.
509-
#[inline(always)]
510-
fn is_dynamic(&self) -> bool {
511-
self.tag() == DYNAMIC_TAG
512-
}
513-
}
514-
515-
impl Default for Wtf8Atom {
516-
#[inline(never)]
517-
fn default() -> Self {
518-
Wtf8Atom::new("")
519-
}
520-
}
521-
522-
/// Immutable, so it's safe to be shared between threads
523-
unsafe impl Send for Wtf8Atom {}
524-
525-
/// Immutable, so it's safe to be shared between threads
526-
unsafe impl Sync for Wtf8Atom {}
527-
528-
impl Debug for Wtf8Atom {
529-
#[inline]
530-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
531-
Debug::fmt(&self.to_string_lossy(), f)
532-
}
533-
}
534-
535-
#[cfg(feature = "serde")]
536-
impl serde::ser::Serialize for Wtf8Atom {
537-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
538-
where
539-
S: serde::ser::Serializer,
540-
{
541-
serializer.serialize_bytes(self.as_bytes())
542-
}
543-
}
544-
545-
#[cfg(feature = "serde")]
546-
impl<'de> serde::de::Deserialize<'de> for Wtf8Atom {
547-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
548-
where
549-
D: serde::Deserializer<'de>,
550-
{
551-
String::deserialize(deserializer).map(Self::new)
552-
}
553-
}
554-
555-
impl PartialEq for Wtf8Atom {
556-
#[inline(never)]
557-
fn eq(&self, other: &Self) -> bool {
558-
partial_eq!(self, other);
559-
560-
// If the store is different, the string may be the same, even though the
561-
// `unsafe_data` is different
562-
self.as_wtf8() == other.as_wtf8()
563-
}
564-
}
565-
566-
impl Eq for Wtf8Atom {}
567-
568-
impl Hash for Wtf8Atom {
569-
#[inline(always)]
570-
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
571-
state.write_u64(self.get_hash());
572-
}
573-
}
574-
575-
impl Drop for Wtf8Atom {
576-
#[inline(always)]
577-
fn drop(&mut self) {
578-
if self.is_dynamic() {
579-
unsafe { drop(crate::dynamic::restore_arc(self.unsafe_data)) }
580-
}
581-
}
582-
}
583-
584-
impl Clone for Wtf8Atom {
585-
#[inline(always)]
586-
fn clone(&self) -> Self {
587-
Self::from_alias(self.unsafe_data)
588-
}
589-
}
590-
591-
impl Deref for Wtf8Atom {
592-
type Target = Wtf8;
593-
594-
#[inline(always)]
595-
fn deref(&self) -> &Self::Target {
596-
self.as_wtf8()
597-
}
598-
}
599-
600-
impl AsRef<Wtf8> for Wtf8Atom {
601-
#[inline(always)]
602-
fn as_ref(&self) -> &Wtf8 {
603-
self.as_wtf8()
604-
}
605-
}
606-
607-
impl PartialEq<Wtf8> for Wtf8Atom {
608-
#[inline]
609-
fn eq(&self, other: &Wtf8) -> bool {
610-
self.as_wtf8() == other
611-
}
612-
}
613-
614-
impl PartialEq<Atom> for Wtf8Atom {
615-
#[inline]
616-
fn eq(&self, other: &Atom) -> bool {
617-
self.as_str() == Some(other.as_str())
618-
}
619-
}
620-
621-
impl PartialEq<&'_ Wtf8> for Wtf8Atom {
622-
#[inline]
623-
fn eq(&self, other: &&Wtf8) -> bool {
624-
self.as_wtf8() == *other
625-
}
626-
}
627-
628-
impl PartialEq<Wtf8Atom> for Wtf8 {
629-
#[inline]
630-
fn eq(&self, other: &Wtf8Atom) -> bool {
631-
self == other.as_wtf8()
632-
}
633-
}
634-
635-
impl Wtf8Atom {
636-
fn get_hash(&self) -> u64 {
637-
get_hash!(self)
638-
}
639-
640-
fn as_wtf8(&self) -> &Wtf8 {
641-
match self.tag() {
642-
DYNAMIC_TAG => unsafe {
643-
let item = crate::dynamic::deref_from(self.unsafe_data);
644-
Wtf8::from_bytes(transmute::<&[u8], &'static [u8]>(&item.slice))
645-
},
646-
INLINE_TAG => {
647-
let len = (self.unsafe_data.tag() & LEN_MASK) >> LEN_OFFSET;
648-
let src = self.unsafe_data.data();
649-
Wtf8::from_bytes(&src[..(len as usize)])
650-
}
651-
_ => unsafe { debug_unreachable!() },
652-
}
653-
}
654-
}
655-
656-
impl_from_alias!(Wtf8Atom);
657-
658-
#[cfg(test)]
659-
impl Wtf8Atom {
660-
pub(crate) fn ref_count(&self) -> usize {
661-
match self.tag() {
662-
DYNAMIC_TAG => {
663-
let ptr = unsafe { crate::dynamic::deref_from(self.unsafe_data) };
664-
665-
triomphe::ThinArc::strong_count(&ptr.0)
666-
}
667-
_ => 1,
668-
}
669-
}
670-
}
671-
672427
#[cfg(test)]
673428
mod macro_tests {
674429

crates/hstr/src/macros.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
macro_rules! get_hash {
2+
($self:expr) => {
3+
match $self.tag() {
4+
DYNAMIC_TAG => {
5+
let unsafe_data = $self.unsafe_data;
6+
unsafe { $crate::dynamic::deref_from(unsafe_data) }
7+
.header
8+
.header
9+
.hash
10+
}
11+
INLINE_TAG => {
12+
// This is passed as input to the caller's `Hasher` implementation, so it's okay
13+
// that this isn't really a hash
14+
$self.unsafe_data.hash()
15+
}
16+
_ => unsafe { debug_unreachable!() },
17+
}
18+
};
19+
}
20+
21+
macro_rules! partial_eq {
22+
($self:expr, $other:expr) => {
23+
if $self.unsafe_data == $other.unsafe_data {
24+
return true;
25+
}
26+
27+
// If one is inline and the other is not, the length is different.
28+
// If one is static and the other is not, it's different.
29+
if $self.tag() != $other.tag() {
30+
return false;
31+
}
32+
33+
if $self.is_dynamic() && $other.is_dynamic() {
34+
let te = unsafe { $crate::dynamic::deref_from($self.unsafe_data) };
35+
let oe = unsafe { $crate::dynamic::deref_from($other.unsafe_data) };
36+
37+
if te.header.header.hash != oe.header.header.hash {
38+
return false;
39+
}
40+
41+
return te.slice == oe.slice;
42+
}
43+
44+
if $self.get_hash() != $other.get_hash() {
45+
return false;
46+
}
47+
};
48+
}
49+
50+
macro_rules! impl_from_alias {
51+
($ty:ty) => {
52+
impl $ty {
53+
#[inline]
54+
pub(crate) fn from_alias(alias: TaggedValue) -> Self {
55+
if alias.tag() & TAG_MASK == DYNAMIC_TAG {
56+
unsafe {
57+
let arc = $crate::dynamic::restore_arc(alias);
58+
forget(arc.clone());
59+
forget(arc);
60+
}
61+
}
62+
63+
Self { unsafe_data: alias }
64+
}
65+
}
66+
};
67+
}
68+
69+
pub(crate) use get_hash;
70+
pub(crate) use impl_from_alias;
71+
pub(crate) use partial_eq;

0 commit comments

Comments
 (0)