Clash.Meta/rules/provider/mrs_reader.go
2024-07-27 10:36:11 +08:00

73 lines
1.4 KiB
Go

package provider
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"github.com/klauspost/compress/zstd"
)
var MrsMagicBytes = [4]byte{'M', 'R', 'S', 1} // MRSv1
func rulesMrsParse(buf []byte, strategy ruleStrategy) (ruleStrategy, error) {
if _strategy, ok := strategy.(mrsRuleStrategy); ok {
reader, err := zstd.NewReader(bytes.NewReader(buf))
if err != nil {
return nil, err
}
defer reader.Close()
// header
var header [4]byte
_, err = io.ReadFull(reader, header[:])
if err != nil {
return nil, err
}
if header != MrsMagicBytes {
return nil, fmt.Errorf("invalid MrsMagic bytes")
}
// behavior
var _behavior [1]byte
_, err = io.ReadFull(reader, _behavior[:])
if err != nil {
return nil, err
}
if _behavior[0] != strategy.Behavior().Byte() {
return nil, fmt.Errorf("invalid behavior")
}
// count
var count int64
err = binary.Read(reader, binary.BigEndian, &count)
if err != nil {
return nil, err
}
// extra (reserved for future using)
var length int64
err = binary.Read(reader, binary.BigEndian, &length)
if err != nil {
return nil, err
}
if length < 0 {
return nil, errors.New("length is invalid")
}
if length > 0 {
extra := make([]byte, length)
_, err = io.ReadFull(reader, extra)
if err != nil {
return nil, err
}
}
err = _strategy.FromMrs(reader, int(count))
return strategy, err
} else {
return nil, ErrInvalidFormat
}
}