123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- package provider
- import (
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "os"
- P "github.com/metacubex/mihomo/constant/provider"
- "github.com/klauspost/compress/zstd"
- )
- func ConvertToMrs(buf []byte, behavior P.RuleBehavior, format P.RuleFormat, w io.Writer) (err error) {
- strategy := newStrategy(behavior, nil)
- strategy, err = rulesParse(buf, strategy, format)
- if err != nil {
- return err
- }
- if strategy.Count() == 0 {
- return errors.New("empty rule")
- }
- if _strategy, ok := strategy.(mrsRuleStrategy); ok {
- if format == P.MrsRule { // export to TextRule
- _strategy.DumpMrs(func(key string) bool {
- _, err = fmt.Fprintln(w, key)
- if err != nil {
- return false
- }
- return true
- })
- return nil
- }
- var encoder *zstd.Encoder
- encoder, err = zstd.NewWriter(w)
- if err != nil {
- return err
- }
- defer func() {
- zstdErr := encoder.Close()
- if err == nil {
- err = zstdErr
- }
- }()
- // header
- _, err = encoder.Write(MrsMagicBytes[:])
- if err != nil {
- return err
- }
- // behavior
- _behavior := []byte{behavior.Byte()}
- _, err = encoder.Write(_behavior[:])
- if err != nil {
- return err
- }
- // count
- count := int64(_strategy.Count())
- err = binary.Write(encoder, binary.BigEndian, count)
- if err != nil {
- return err
- }
- // extra (reserved for future using)
- var extra []byte
- err = binary.Write(encoder, binary.BigEndian, int64(len(extra)))
- if err != nil {
- return err
- }
- _, err = encoder.Write(extra)
- if err != nil {
- return err
- }
- return _strategy.WriteMrs(encoder)
- } else {
- return ErrInvalidFormat
- }
- }
- func ConvertMain(args []string) {
- if len(args) > 3 {
- behavior, err := P.ParseBehavior(args[0])
- if err != nil {
- panic(err)
- }
- format, err := P.ParseRuleFormat(args[1])
- if err != nil {
- panic(err)
- }
- source := args[2]
- target := args[3]
- sourceFile, err := os.ReadFile(source)
- if err != nil {
- panic(err)
- }
- targetFile, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- if err != nil {
- panic(err)
- }
- err = ConvertToMrs(sourceFile, behavior, format, targetFile)
- if err != nil {
- panic(err)
- }
- err = targetFile.Close()
- if err != nil {
- panic(err)
- }
- } else {
- panic("Usage: convert-ruleset <behavior> <format> <source file> <target file>")
- }
- }
|