(mc: &Mutation<'gc>, s: Box<[u8]>)
| 41 | |
| 42 | impl<'gc> InternedString<'gc> { |
| 43 | pub fn from_buffer(mc: &Mutation<'gc>, s: Box<[u8]>) -> InternedString<'gc> { |
| 44 | #[derive(Collect)] |
| 45 | #[collect(require_static)] |
| 46 | #[repr(C)] |
| 47 | struct Owned { |
| 48 | header: StringInner, |
| 49 | metrics: Metrics, |
| 50 | } |
| 51 | |
| 52 | impl Drop for Owned { |
| 53 | fn drop(&mut self) { |
| 54 | match self.header.buffer { |
| 55 | Buffer::Indirect(ptr) => unsafe { |
| 56 | self.metrics.mark_external_deallocation((*ptr).len()); |
| 57 | drop(Box::from_raw(ptr as *mut [u8])); |
| 58 | }, |
| 59 | Buffer::Inline(_) => unreachable!(), |
| 60 | } |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | let metrics = mc.metrics().clone(); |
| 65 | metrics.mark_external_allocation(s.len()); |
| 66 | let owned = Owned { |
| 67 | header: StringInner { |
| 68 | hash: str_hash(&s), |
| 69 | buffer: Buffer::Indirect(Box::into_raw(s)), |
| 70 | }, |
| 71 | metrics, |
| 72 | }; |
| 73 | // SAFETY: We know we can cast to `StringInner` because `Owned` is `#[repr(C)]` |
| 74 | InternedString(unsafe { Gc::cast::<StringInner>(Gc::new(mc, owned)) }) |
| 75 | } |
| 76 | |
| 77 | pub fn from_slice(mc: &Mutation<'gc>, s: impl AsRef<[u8]>) -> InternedString<'gc> { |
| 78 | // TODO: This is an extremely silly way to allocate a dynamically sized, inline string. |
nothing calls this directly
no test coverage detected