11use std:: io:: Write ;
22
3+ use bitvec:: field:: BitField ;
4+ use bitvec:: order:: Lsb0 ;
5+ use bitvec:: view:: BitView ;
36use serde_json:: Value ;
47
58use crate :: errors:: Result ;
@@ -21,6 +24,78 @@ fn encode_vlq_diff(out: &mut String, a: u32, b: u32) {
2124 encode_vlq ( out, i64:: from ( a) - i64:: from ( b) )
2225}
2326
27+ fn encode_rmi ( out : & mut Vec < u8 > , data : & mut Vec < u8 > ) {
28+ fn encode_byte ( b : u8 ) -> u8 {
29+ match b {
30+ 0 ..=25 => b + b'A' ,
31+ 26 ..=51 => b + b'a' - 26 ,
32+ 52 ..=61 => b + b'0' - 52 ,
33+ 62 => b'+' ,
34+ 63 => b'/' ,
35+ _ => panic ! ( "invalid byte" ) ,
36+ }
37+ }
38+
39+ let bits = data. view_bits_mut :: < Lsb0 > ( ) ;
40+
41+ // trim zero at the end
42+ let mut last = 0 ;
43+ for ( idx, bit) in bits. iter ( ) . enumerate ( ) {
44+ if * bit {
45+ last = idx;
46+ }
47+ }
48+ let bits = & mut bits[ ..last + 1 ] ;
49+
50+ for byte in bits. chunks ( 6 ) {
51+ let byte = byte. load :: < u8 > ( ) ;
52+
53+ let encoded = encode_byte ( byte) ;
54+
55+ out. push ( encoded) ;
56+ }
57+ }
58+
59+ fn serialize_range_mappings ( sm : & SourceMap ) -> Option < String > {
60+ let mut buf = Vec :: new ( ) ;
61+ let mut prev_line = 0 ;
62+ let mut had_rmi = false ;
63+
64+ let mut idx_of_first_in_line = 0 ;
65+
66+ let mut rmi_data = Vec :: < u8 > :: new ( ) ;
67+
68+ for ( idx, token) in sm. tokens ( ) . enumerate ( ) {
69+ if token. is_range ( ) {
70+ had_rmi = true ;
71+
72+ let num = idx - idx_of_first_in_line;
73+
74+ rmi_data. resize ( rmi_data. len ( ) + 2 , 0 ) ;
75+
76+ let rmi_bits = rmi_data. view_bits_mut :: < Lsb0 > ( ) ;
77+ rmi_bits. set ( num, true ) ;
78+ }
79+
80+ while token. get_dst_line ( ) != prev_line {
81+ if had_rmi {
82+ encode_rmi ( & mut buf, & mut rmi_data) ;
83+ rmi_data. clear ( ) ;
84+ }
85+
86+ buf. push ( b';' ) ;
87+ prev_line += 1 ;
88+ had_rmi = false ;
89+ idx_of_first_in_line = idx;
90+ }
91+ }
92+ if had_rmi {
93+ encode_rmi ( & mut buf, & mut rmi_data) ;
94+ }
95+
96+ Some ( String :: from_utf8 ( buf) . expect ( "invalid utf8" ) )
97+ }
98+
2499fn serialize_mappings ( sm : & SourceMap ) -> String {
25100 let mut rv = String :: new ( ) ;
26101 // dst == minified == generated
@@ -89,6 +164,7 @@ impl Encodable for SourceMap {
89164 sources_content : if have_contents { Some ( contents) } else { None } ,
90165 sections : None ,
91166 names : Some ( self . names ( ) . map ( |x| Value :: String ( x. to_string ( ) ) ) . collect ( ) ) ,
167+ range_mappings : serialize_range_mappings ( self ) ,
92168 mappings : Some ( serialize_mappings ( self ) ) ,
93169 x_facebook_offsets : None ,
94170 x_metro_module_paths : None ,
@@ -121,6 +197,7 @@ impl Encodable for SourceMapIndex {
121197 . collect ( ) ,
122198 ) ,
123199 names : None ,
200+ range_mappings : None ,
124201 mappings : None ,
125202 x_facebook_offsets : None ,
126203 x_metro_module_paths : None ,
@@ -139,3 +216,26 @@ impl Encodable for DecodedMap {
139216 }
140217 }
141218}
219+
220+ #[ test]
221+ fn test_encode_rmi ( ) {
222+ fn encode ( indices : & [ usize ] ) -> String {
223+ let mut out = vec ! [ ] ;
224+
225+ // Fill with zeros while testing
226+ let mut data = vec ! [ 0 ; 256 ] ;
227+
228+ let bits = data. view_bits_mut :: < Lsb0 > ( ) ;
229+ for & i in indices {
230+ bits. set ( i, true ) ;
231+ }
232+
233+ encode_rmi ( & mut out, & mut data) ;
234+ String :: from_utf8 ( out) . unwrap ( )
235+ }
236+
237+ // This is 0-based index
238+ assert_eq ! ( encode( & [ 12 ] ) , "AAB" ) ;
239+ assert_eq ! ( encode( & [ 5 ] ) , "g" ) ;
240+ assert_eq ! ( encode( & [ 0 , 11 ] ) , "Bg" ) ;
241+ }
0 commit comments