Files
wehub-resource-sync 48b3ccf279
Test / test (windows-latest) (push) Waiting to run
gitleaks / gitleaks (push) Has been skipped
Test / test (ubuntu-latest) (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:12:29 +08:00

106 lines
2.7 KiB
Go

package codec
import (
"bytes"
"github.com/zricethezav/gitleaks/v8/logging"
)
// Decoder decodes various types of data in place
type Decoder struct {
decodedMap map[string]string
}
// NewDecoder creates a default decoder struct
func NewDecoder() *Decoder {
return &Decoder{
decodedMap: make(map[string]string),
}
}
// Decode returns the data with the values decoded in place along with the
// encoded segment meta data for the next pass of decoding
func (d *Decoder) Decode(data string, predecessors []*EncodedSegment) (string, []*EncodedSegment) {
segments := d.findEncodedSegments(data, predecessors)
if len(segments) > 0 {
result := bytes.NewBuffer(make([]byte, 0, len(data)))
encodedStart := 0
for _, segment := range segments {
result.WriteString(data[encodedStart:segment.encoded.start])
result.WriteString(segment.decodedValue)
encodedStart = segment.encoded.end
}
result.WriteString(data[encodedStart:])
return result.String(), segments
}
return data, segments
}
// findEncodedSegments finds the encoded segments in the data
func (d *Decoder) findEncodedSegments(data string, predecessors []*EncodedSegment) []*EncodedSegment {
if len(data) == 0 {
return []*EncodedSegment{}
}
decodedShift := 0
encodingMatches := findEncodingMatches(data)
segments := make([]*EncodedSegment, 0, len(encodingMatches))
for _, m := range encodingMatches {
encodedValue := data[m.start:m.end]
decodedValue, alreadyDecoded := d.decodedMap[encodedValue]
if !alreadyDecoded {
decodedValue = m.encoding.decode(encodedValue)
d.decodedMap[encodedValue] = decodedValue
}
if len(decodedValue) == 0 {
continue
}
segment := &EncodedSegment{
predecessors: predecessors,
original: toOriginal(predecessors, m.startEnd),
encoded: m.startEnd,
decoded: startEnd{
m.start + decodedShift,
m.start + decodedShift + len(decodedValue),
},
decodedValue: decodedValue,
encodings: m.encoding.kind,
depth: 1,
}
// Shift decoded start and ends based on size changes
decodedShift += len(decodedValue) - len(encodedValue)
// Adjust depth and encoding if applicable
if len(segment.predecessors) != 0 {
// Set the depth based on the predecessors' depth in the previous pass
segment.depth = 1 + segment.predecessors[0].depth
// Adjust encodings
for _, p := range segment.predecessors {
if segment.encoded.overlaps(p.decoded) {
segment.encodings |= p.encodings
}
}
}
segments = append(segments, segment)
logging.Debug().
Str("decoder", m.encoding.kind.String()).
Msgf(
"segment found: original=%s pos=%s: %q -> %q",
segment.original,
segment.encoded,
encodedValue,
segment.decodedValue,
)
}
return segments
}