1use crate::vlq::vlq_decode;
2use crate::{DecodeError, Line, Segment, SourceMapMappings};
3
4pub fn decode(input: &str) -> Result<SourceMapMappings, DecodeError> {
20 if input.is_empty() {
21 return Ok(Vec::new());
22 }
23
24 let bytes = input.as_bytes();
25 let len = bytes.len();
26
27 let mut semicolons = 0usize;
29 let mut commas = 0usize;
30 for &b in bytes {
31 semicolons += (b == b';') as usize;
32 commas += (b == b',') as usize;
33 }
34 let line_count = semicolons + 1;
35 let approx_segments = commas + line_count;
36 let avg_segments_per_line = approx_segments / line_count;
37 let mut mappings: SourceMapMappings = Vec::with_capacity(line_count);
38
39 let mut source_index: i64 = 0;
41 let mut original_line: i64 = 0;
42 let mut original_column: i64 = 0;
43 let mut name_index: i64 = 0;
44
45 let mut pos: usize = 0;
46
47 loop {
48 let mut generated_column: i64 = 0;
50 let mut line: Line = Vec::with_capacity(avg_segments_per_line);
51 let mut saw_semicolon = false;
52
53 while pos < len {
54 let byte = bytes[pos];
55
56 if byte == b';' {
57 pos += 1;
58 saw_semicolon = true;
59 break;
60 }
61
62 if byte == b',' {
63 pos += 1;
64 continue;
65 }
66
67 let (delta, consumed) = vlq_decode(bytes, pos)?;
69 generated_column += delta;
70 pos += consumed;
71
72 let segment: Segment = if pos < len && bytes[pos] != b',' && bytes[pos] != b';' {
74 let (delta, consumed) = vlq_decode(bytes, pos)?;
76 source_index += delta;
77 pos += consumed;
78
79 if pos >= len || bytes[pos] == b',' || bytes[pos] == b';' {
81 return Err(DecodeError::InvalidSegmentLength {
82 fields: 2,
83 offset: pos,
84 });
85 }
86
87 let (delta, consumed) = vlq_decode(bytes, pos)?;
89 original_line += delta;
90 pos += consumed;
91
92 if pos >= len || bytes[pos] == b',' || bytes[pos] == b';' {
94 return Err(DecodeError::InvalidSegmentLength {
95 fields: 3,
96 offset: pos,
97 });
98 }
99
100 let (delta, consumed) = vlq_decode(bytes, pos)?;
102 original_column += delta;
103 pos += consumed;
104
105 if pos < len && bytes[pos] != b',' && bytes[pos] != b';' {
107 let (delta, consumed) = vlq_decode(bytes, pos)?;
108 name_index += delta;
109 pos += consumed;
110 Segment::five(
111 generated_column,
112 source_index,
113 original_line,
114 original_column,
115 name_index,
116 )
117 } else {
118 Segment::four(
119 generated_column,
120 source_index,
121 original_line,
122 original_column,
123 )
124 }
125 } else {
126 Segment::one(generated_column)
127 };
128
129 line.push(segment);
130 }
131
132 mappings.push(line);
133
134 if !saw_semicolon {
135 break;
136 }
137 }
138
139 Ok(mappings)
140}