11// Copyright (c) Microsoft Corporation.
22// Licensed under the MIT License.
33
4- use std:: collections:: HashMap ;
5- use std:: sync:: Mutex ;
6-
74use anyhow:: Result ;
8- use thiserror:: Error ;
95
106use crate :: path:: FilePath ;
117
12- #[ derive( Clone , Copy ) ]
13- struct Leaked ( & ' static [ u8 ] ) ;
14-
15- impl Leaked {
16- pub fn into_raw ( self ) -> * mut [ u8 ] {
17- self . 0 as * const _ as * mut _
18- }
19- }
20-
21- impl From < Vec < u8 > > for Leaked {
22- fn from ( data : Vec < u8 > ) -> Self {
23- let data = Box :: leak ( data. into_boxed_slice ( ) ) ;
24- Leaked ( data)
25- }
26- }
27-
288#[ derive( Default ) ]
299pub struct Loader {
30- loaded : Mutex < HashMap < FilePath , Leaked > > ,
10+ loaded : elsa :: FrozenMap < FilePath , Box < [ u8 ] > > ,
3111}
3212
3313impl Loader {
@@ -36,49 +16,11 @@ impl Loader {
3616 }
3717
3818 pub fn load ( & self , path : & FilePath ) -> Result < & [ u8 ] > {
39- if let Some ( data) = self . get ( path) ? {
40- Ok ( data)
41- } else {
42- self . load_new ( path)
19+ if let Some ( data) = self . loaded . get ( path) {
20+ return Ok ( data) ;
4321 }
44- }
4522
46- fn load_new ( & self , path : & FilePath ) -> Result < & [ u8 ] > {
47- let mut loaded = self . loaded . lock ( ) . map_err ( |_| LoaderError :: PoisonedMutex ) ?;
48- let data = std:: fs:: read ( path) ?;
49- let leaked = Leaked :: from ( data) ;
50- loaded. insert ( path. clone ( ) , leaked) ;
51-
52- Ok ( leaked. 0 )
23+ let data: Box < [ u8 ] > = std:: fs:: read ( path) ?. into ( ) ;
24+ Ok ( self . loaded . insert ( path. clone ( ) , data) )
5325 }
54-
55- pub fn get ( & self , path : & FilePath ) -> Result < Option < & [ u8 ] > > {
56- let loaded = self . loaded . lock ( ) . map_err ( |_| LoaderError :: PoisonedMutex ) ?;
57-
58- let data = loaded. get ( path) . map ( |l| l. 0 ) ;
59-
60- Ok ( data)
61- }
62- }
63-
64- impl Drop for Loader {
65- fn drop ( & mut self ) {
66- if let Ok ( mut loaded) = self . loaded . lock ( ) {
67- for ( _, leaked) in loaded. drain ( ) {
68- unsafe {
69- let raw = leaked. into_raw ( ) ;
70- let owned = Box :: from_raw ( raw) ;
71- drop ( owned) ;
72- }
73- }
74-
75- debug_assert ! ( loaded. is_empty( ) ) ;
76- }
77- }
78- }
79-
80- #[ derive( Error , Debug ) ]
81- pub enum LoaderError {
82- #[ error( "internal mutex poisoned" ) ]
83- PoisonedMutex ,
8426}
0 commit comments