@@ -8,6 +8,15 @@ use crate::{
88use core:: { fmt, mem, num:: NonZeroU32 } ;
99use wasmtime_core:: alloc:: TryClone ;
1010
11+ /// An interned string associated with a particular string in a `StringPool`.
12+ ///
13+ /// Allows for $O(1)$ equality tests, $O(1)$ hashing, and $O(1)$
14+ /// arbitrary-but-stable ordering.
15+ #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
16+ pub struct Atom {
17+ index : NonZeroU32 ,
18+ }
19+
1120/// A pool of interned strings.
1221///
1322/// Insert new strings with [`StringPool::insert`] to get an `Atom` that is
@@ -44,15 +53,6 @@ impl Drop for StringPool {
4453 }
4554}
4655
47- /// An interned string associated with a particular string in a `StringPool`.
48- ///
49- /// Allows for $O(1)$ equality tests, $O(1)$ hashing, and $O(1)$
50- /// arbitrary-but-stable ordering.
51- #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
52- pub struct Atom {
53- index : NonZeroU32 ,
54- }
55-
5656impl fmt:: Debug for StringPool {
5757 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
5858 struct Strings < ' a > ( & ' a StringPool ) ;
@@ -101,6 +101,59 @@ impl core::ops::Index<Atom> for StringPool {
101101 }
102102}
103103
104+ impl serde:: ser:: Serialize for StringPool {
105+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
106+ where
107+ S : serde:: Serializer ,
108+ {
109+ serde:: ser:: Serialize :: serialize ( & * self . strings , serializer)
110+ }
111+ }
112+
113+ impl < ' de > serde:: de:: Deserialize < ' de > for StringPool {
114+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
115+ where
116+ D : serde:: Deserializer < ' de > ,
117+ {
118+ struct Visitor ;
119+ impl < ' de > serde:: de:: Visitor < ' de > for Visitor {
120+ type Value = StringPool ;
121+
122+ fn expecting ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
123+ f. write_str ( "a `StringPool` sequence of strings" )
124+ }
125+
126+ fn visit_seq < A > ( self , mut seq : A ) -> Result < Self :: Value , A :: Error >
127+ where
128+ A : serde:: de:: SeqAccess < ' de > ,
129+ {
130+ use serde:: de:: Error as _;
131+
132+ let mut pool = StringPool :: new ( ) ;
133+
134+ if let Some ( len) = seq. size_hint ( ) {
135+ pool. map . reserve ( len) . map_err ( |oom| A :: Error :: custom ( oom) ) ?;
136+ pool. strings
137+ . reserve ( len)
138+ . map_err ( |oom| A :: Error :: custom ( oom) ) ?;
139+ }
140+
141+ while let Some ( s) = seq. next_element :: < String > ( ) ? {
142+ debug_assert_eq ! ( s. len( ) , s. capacity( ) ) ;
143+ let s = s. into_boxed_str ( ) . map_err ( |oom| A :: Error :: custom ( oom) ) ?;
144+ if !pool. map . contains_key ( & * s) {
145+ pool. insert_new_boxed_str ( s)
146+ . map_err ( |oom| A :: Error :: custom ( oom) ) ?;
147+ }
148+ }
149+
150+ Ok ( pool)
151+ }
152+ }
153+ deserializer. deserialize_seq ( Visitor )
154+ }
155+ }
156+
104157impl StringPool {
105158 /// Create a new, empty pool.
106159 pub fn new ( ) -> Self {
@@ -123,15 +176,21 @@ impl StringPool {
123176 . into_boxed_str ( )
124177 . expect ( "reserved exact capacity, so shouldn't need to realloc" ) ;
125178
179+ self . insert_new_boxed_str ( owned)
180+ }
181+
182+ fn insert_new_boxed_str ( & mut self , owned : Box < str > ) -> Result < Atom , OutOfMemory > {
183+ debug_assert ! ( !self . map. contains_key( & * owned) ) ;
184+
126185 let index = self . strings . len ( ) ;
127186 let atom = Atom :: new ( index) ;
128- self . strings . push ( owned) . expect ( "reserved capacity" ) ;
187+ self . strings . push ( owned) ? ;
129188
130189 // SAFETY: We never expose this borrow and never mutate or reallocate
131190 // strings once inserted into the pool.
132191 let s = unsafe { mem:: transmute :: < & str , & ' static str > ( & self . strings [ index] ) } ;
133192
134- let old = self . map . insert ( s, atom) . expect ( "reserved capacity" ) ;
193+ let old = self . map . insert ( s, atom) ? ;
135194 debug_assert ! ( old. is_none( ) ) ;
136195
137196 Ok ( atom)
@@ -169,6 +228,25 @@ impl fmt::Debug for Atom {
169228 }
170229}
171230
231+ impl serde:: ser:: Serialize for Atom {
232+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
233+ where
234+ S : serde:: Serializer ,
235+ {
236+ serde:: ser:: Serialize :: serialize ( & self . index , serializer)
237+ }
238+ }
239+
240+ impl < ' de > serde:: de:: Deserialize < ' de > for Atom {
241+ fn deserialize < D > ( deserializer : D ) -> core:: result:: Result < Self , D :: Error >
242+ where
243+ D : serde:: Deserializer < ' de > ,
244+ {
245+ let index = serde:: de:: Deserialize :: deserialize ( deserializer) ?;
246+ Ok ( Self { index } )
247+ }
248+ }
249+
172250impl Atom {
173251 fn new ( index : usize ) -> Self {
174252 assert ! ( index < usize :: try_from( u32 :: MAX ) . unwrap( ) ) ;
@@ -235,4 +313,25 @@ mod tests {
235313
236314 Ok ( ( ) )
237315 }
316+
317+ #[ test]
318+ fn roundtrip_serialize_deserialize ( ) -> Result < ( ) > {
319+ let mut pool = StringPool :: new ( ) ;
320+ let a = pool. insert ( "a" ) ?;
321+ let b = pool. insert ( "b" ) ?;
322+ let c = pool. insert ( "c" ) ?;
323+
324+ let bytes = postcard:: to_allocvec ( & ( pool, a, b, c) ) ?;
325+ let ( pool, a2, b2, c2) = postcard:: from_bytes :: < ( StringPool , Atom , Atom , Atom ) > ( & bytes) ?;
326+
327+ assert_eq ! ( & pool[ a] , "a" ) ;
328+ assert_eq ! ( & pool[ b] , "b" ) ;
329+ assert_eq ! ( & pool[ c] , "c" ) ;
330+
331+ assert_eq ! ( & pool[ a2] , "a" ) ;
332+ assert_eq ! ( & pool[ b2] , "b" ) ;
333+ assert_eq ! ( & pool[ c2] , "c" ) ;
334+
335+ Ok ( ( ) )
336+ }
238337}
0 commit comments