Advertisement
Guest User

Untitled

a guest
Sep 8th, 2024
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 2.46 KB | Source Code | 0 0
  1. use std::cell::RefCell;
  2. use std::collections::HashMap;
  3. use std::fmt;
  4. use std::fmt::{Display, Formatter};
  5. use std::mem;
  6.  
  7. pub struct Interned<'a> {
  8.    index: usize,
  9.    parent: &'a StrManager,
  10. }
  11.  
  12. impl<'a> Display for Interned<'a> {
  13.     fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> {
  14.        self.parent.internals.borrow().string_locations[self.index].fmt(fmt)
  15.    }
  16. }
  17.  
  18. impl<'a> PartialEq for Interned<'a> {
  19.    fn eq(&self, other: &Self) -> bool {
  20.        self.index == other.index && std::ptr::eq(self.parent, other.parent)
  21.    }
  22. }
  23.  
  24. struct StrManagerInternals {
  25.    strings: HashMap<&'static str, usize>,
  26.     string_locations: Vec<&'static str>,
  27.    buffer: String,
  28.    full_buffers: Vec<String>,
  29. }
  30.  
  31. pub struct StrManager {
  32.    internals: RefCell<StrManagerInternals>,
  33. }
  34.  
  35. impl StrManager {
  36.    pub fn with_capacity(cap: usize) -> Self {
  37.        StrManager {
  38.            internals: RefCell::new(StrManagerInternals {
  39.                strings: HashMap::new(),
  40.                string_locations: Vec::new(),
  41.                buffer: String::with_capacity(cap.next_power_of_two()),
  42.                full_buffers: Vec::new(),
  43.            }),
  44.        }
  45.    }
  46.    pub fn new() -> Self {
  47.        StrManager::with_capacity(128)
  48.    }
  49.  
  50.    pub fn intern<'a>(&'a mut self, s: &str) -> Interned<'a> {
  51.         if let Some(&index) = self.internals.borrow().strings.get(s) {
  52.             return Interned {
  53.                 index,
  54.                 parent: self,
  55.             };
  56.         }
  57.  
  58.         let interned = unsafe { self.alloc(s) };
  59.         let index = self.internals.borrow().string_locations.len();
  60.         self.internals.borrow_mut().string_locations.push(interned);
  61.  
  62.         Interned {
  63.             index,
  64.             parent: self,
  65.         }
  66.     }
  67.  
  68.     unsafe fn alloc(&self, s: &str) -> &'static str {
  69.        let mut internals = self.internals.borrow_mut();
  70.        let cap = internals.buffer.capacity();
  71.        if cap < internals.buffer.len() + s.len() {
  72.            let new_cap = (cap.max(s.len()) + 1).next_power_of_two();
  73.            let new_buf = String::with_capacity(new_cap);
  74.            let old_buf = mem::replace(&mut internals.buffer, new_buf);
  75.            internals.full_buffers.push(old_buf);
  76.        }
  77.  
  78.        let interned = {
  79.            let start = internals.buffer.len();
  80.            internals.buffer.push_str(s);
  81.            &internals.buffer[start..]
  82.        };
  83.  
  84.        &*(interned as *const str)
  85.    }
  86. }
  87.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement