sugarloaf 0.1.6

Sugarloaf is Rio rendering engine, designed to be multiplatform. It is based on WebGPU, Rust library for Desktops and WebAssembly for Web (JavaScript). This project is created and maintained for Rio terminal purposes but feel free to use it.
Documentation
// Copyright (c) 2023-present, Raphael Amorim.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//
// string.rs was originally retired from dfrg/swash_demo licensed under MIT
// https://github.com/dfrg/swash_demo/blob/master/LICENSE

use core::borrow::Borrow;
use core::cmp::PartialEq;
use core::fmt;
use core::hash::{Hash, Hasher};
use std::sync::Arc;

const MAX_SMALL_SIZE: usize = 23;
const LEN_SLOT: usize = 23;
const INLINE_BIT: u8 = 0x80;
const LEN_MASK: u8 = !INLINE_BIT;

#[repr(align(8))]
pub struct SmallString {
    bytes: [u8; 24],
}

impl SmallString {
    pub fn new(s: &str) -> Self {
        let len = s.len();
        let mut bytes = [0; 24];
        if len <= MAX_SMALL_SIZE {
            (bytes[..len]).copy_from_slice(s.as_bytes());
            bytes[LEN_SLOT] = (len as u8) | INLINE_BIT;
        } else {
            let arc: Arc<str> = s.into();
            unsafe {
                let ptr: (usize, usize) = core::mem::transmute(arc);
                *(bytes.as_mut_ptr() as *mut (usize, usize)) = ptr;
            }
        }
        Self { bytes }
    }

    pub fn len(&self) -> usize {
        self.as_str().len()
    }

    pub fn is_empty(&self) -> bool {
        self.as_str().len() == 0
    }

    pub fn as_str(&self) -> &str {
        if self.is_inline() {
            let len = (self.bytes[LEN_SLOT] & LEN_MASK) as usize;
            unsafe { core::str::from_utf8_unchecked(&self.bytes[..len]) }
        } else {
            let arc = self.as_arc();
            let s = &*arc as *const str;
            core::mem::forget(arc);
            unsafe { &*s }
        }
    }

    fn is_inline(&self) -> bool {
        self.bytes[LEN_SLOT] & INLINE_BIT != 0
    }

    fn as_arc(&self) -> Arc<str> {
        debug_assert!(!self.is_inline());
        unsafe {
            let ptr = *(self.bytes.as_ptr() as *const [usize; 2]);
            core::mem::transmute(ptr)
        }
    }
}

impl Drop for SmallString {
    fn drop(&mut self) {
        if !self.is_inline() {
            drop(self.as_arc())
        }
    }
}

impl Clone for SmallString {
    fn clone(&self) -> Self {
        if !self.is_inline() {
            let arc = self.as_arc();
            core::mem::forget(Arc::clone(&arc));
            core::mem::forget(arc);
        }
        Self { bytes: self.bytes }
    }
}

impl Borrow<str> for SmallString {
    fn borrow(&self) -> &str {
        self.as_str()
    }
}

impl PartialEq for SmallString {
    fn eq(&self, other: &Self) -> bool {
        self.as_str().eq(other.as_str())
    }
}

impl Eq for SmallString {}

impl PartialEq<&'_ str> for SmallString {
    fn eq(&self, other: &&'_ str) -> bool {
        self.as_str().eq(*other)
    }
}

impl PartialEq<str> for SmallString {
    fn eq(&self, other: &str) -> bool {
        self.as_str().eq(other)
    }
}

impl PartialEq<SmallString> for str {
    fn eq(&self, other: &SmallString) -> bool {
        self.eq(other.as_str())
    }
}

impl Hash for SmallString {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.as_str().hash(hasher)
    }
}

impl fmt::Debug for SmallString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_str().fmt(f)
    }
}

impl fmt::Display for SmallString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_str().fmt(f)
    }
}

pub struct LowercaseString {
    buf: [u8; 128],
    heap: String,
}

impl Default for LowercaseString {
    fn default() -> Self {
        Self::new()
    }
}

impl LowercaseString {
    pub fn new() -> Self {
        Self {
            buf: [0u8; 128],
            heap: Default::default(),
        }
    }

    pub fn get<'a>(&'a mut self, name: &str) -> Option<&'a str> {
        if name.len() <= self.buf.len() && name.is_ascii() {
            let mut end = 0;
            for c in name.as_bytes() {
                self.buf[end] = c.to_ascii_lowercase();
                end += 1;
            }
            std::str::from_utf8(&self.buf[..end]).ok()
        } else {
            self.heap = name.to_lowercase();
            Some(&self.heap)
        }
    }
}