1package sourcemap 2 3import ( 4 "errors" 5 "io" 6 "strings" 7 8 "github.com/go-sourcemap/sourcemap/internal/base64vlq" 9) 10 11type fn func(m *mappings) (fn, error) 12 13type mapping struct { 14 genLine int32 15 genColumn int32 16 sourcesInd int32 17 sourceLine int32 18 sourceColumn int32 19 namesInd int32 20} 21 22type mappings struct { 23 rd *strings.Reader 24 dec base64vlq.Decoder 25 26 hasName bool 27 value mapping 28 29 values []mapping 30} 31 32func parseMappings(s string) ([]mapping, error) { 33 if s == "" { 34 return nil, errors.New("sourcemap: mappings are empty") 35 } 36 37 rd := strings.NewReader(s) 38 m := &mappings{ 39 rd: rd, 40 dec: base64vlq.NewDecoder(rd), 41 42 values: make([]mapping, 0, mappingsNumber(s)), 43 } 44 m.value.genLine = 1 45 m.value.sourceLine = 1 46 47 err := m.parse() 48 if err != nil { 49 return nil, err 50 } 51 52 values := m.values 53 m.values = nil 54 return values, nil 55} 56 57func mappingsNumber(s string) int { 58 return strings.Count(s, ",") + strings.Count(s, ";") 59} 60 61func (m *mappings) parse() error { 62 next := parseGenCol 63 for { 64 c, err := m.rd.ReadByte() 65 if err == io.EOF { 66 m.pushValue() 67 return nil 68 } 69 if err != nil { 70 return err 71 } 72 73 switch c { 74 case ',': 75 m.pushValue() 76 next = parseGenCol 77 case ';': 78 m.pushValue() 79 80 m.value.genLine++ 81 m.value.genColumn = 0 82 83 next = parseGenCol 84 default: 85 err := m.rd.UnreadByte() 86 if err != nil { 87 return err 88 } 89 90 next, err = next(m) 91 if err != nil { 92 return err 93 } 94 } 95 } 96} 97 98func parseGenCol(m *mappings) (fn, error) { 99 n, err := m.dec.Decode() 100 if err != nil { 101 return nil, err 102 } 103 m.value.genColumn += n 104 return parseSourcesInd, nil 105} 106 107func parseSourcesInd(m *mappings) (fn, error) { 108 n, err := m.dec.Decode() 109 if err != nil { 110 return nil, err 111 } 112 m.value.sourcesInd += n 113 return parseSourceLine, nil 114} 115 116func parseSourceLine(m *mappings) (fn, error) { 117 n, err := m.dec.Decode() 118 if err != nil { 119 return nil, err 120 } 121 m.value.sourceLine += n 122 return parseSourceCol, nil 123} 124 125func parseSourceCol(m *mappings) (fn, error) { 126 n, err := m.dec.Decode() 127 if err != nil { 128 return nil, err 129 } 130 m.value.sourceColumn += n 131 return parseNamesInd, nil 132} 133 134func parseNamesInd(m *mappings) (fn, error) { 135 n, err := m.dec.Decode() 136 if err != nil { 137 return nil, err 138 } 139 m.hasName = true 140 m.value.namesInd += n 141 return parseGenCol, nil 142} 143 144func (m *mappings) pushValue() { 145 if m.value.sourceLine == 1 && m.value.sourceColumn == 0 { 146 return 147 } 148 149 if m.hasName { 150 m.values = append(m.values, m.value) 151 m.hasName = false 152 } else { 153 m.values = append(m.values, mapping{ 154 genLine: m.value.genLine, 155 genColumn: m.value.genColumn, 156 sourcesInd: m.value.sourcesInd, 157 sourceLine: m.value.sourceLine, 158 sourceColumn: m.value.sourceColumn, 159 namesInd: -1, 160 }) 161 } 162} 163