binary.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. package srs
  2. import (
  3. "bufio"
  4. "compress/zlib"
  5. "encoding/binary"
  6. "io"
  7. "net/netip"
  8. "unsafe"
  9. C "github.com/sagernet/sing-box/constant"
  10. "github.com/sagernet/sing-box/option"
  11. "github.com/sagernet/sing/common"
  12. "github.com/sagernet/sing/common/domain"
  13. E "github.com/sagernet/sing/common/exceptions"
  14. "github.com/sagernet/sing/common/json/badjson"
  15. "github.com/sagernet/sing/common/json/badoption"
  16. "github.com/sagernet/sing/common/varbin"
  17. "go4.org/netipx"
  18. )
  19. var MagicBytes = [3]byte{0x53, 0x52, 0x53} // SRS
  20. const (
  21. ruleItemQueryType uint8 = iota
  22. ruleItemNetwork
  23. ruleItemDomain
  24. ruleItemDomainKeyword
  25. ruleItemDomainRegex
  26. ruleItemSourceIPCIDR
  27. ruleItemIPCIDR
  28. ruleItemSourcePort
  29. ruleItemSourcePortRange
  30. ruleItemPort
  31. ruleItemPortRange
  32. ruleItemProcessName
  33. ruleItemProcessPath
  34. ruleItemPackageName
  35. ruleItemWIFISSID
  36. ruleItemWIFIBSSID
  37. ruleItemAdGuardDomain
  38. ruleItemProcessPathRegex
  39. ruleItemNetworkType
  40. ruleItemNetworkIsExpensive
  41. ruleItemNetworkIsConstrained
  42. ruleItemNetworkInterfaceAddress
  43. ruleItemDefaultInterfaceAddress
  44. ruleItemFinal uint8 = 0xFF
  45. )
  46. func Read(reader io.Reader, recover bool) (ruleSetCompat option.PlainRuleSetCompat, err error) {
  47. var magicBytes [3]byte
  48. _, err = io.ReadFull(reader, magicBytes[:])
  49. if err != nil {
  50. return
  51. }
  52. if magicBytes != MagicBytes {
  53. err = E.New("invalid sing-box rule-set file")
  54. return
  55. }
  56. var version uint8
  57. err = binary.Read(reader, binary.BigEndian, &version)
  58. if err != nil {
  59. return ruleSetCompat, err
  60. }
  61. if version > C.RuleSetVersionCurrent {
  62. return ruleSetCompat, E.New("unsupported version: ", version)
  63. }
  64. compressReader, err := zlib.NewReader(reader)
  65. if err != nil {
  66. return
  67. }
  68. bReader := bufio.NewReader(compressReader)
  69. length, err := binary.ReadUvarint(bReader)
  70. if err != nil {
  71. return
  72. }
  73. ruleSetCompat.Version = version
  74. ruleSetCompat.Options.Rules = make([]option.HeadlessRule, length)
  75. for i := uint64(0); i < length; i++ {
  76. ruleSetCompat.Options.Rules[i], err = readRule(bReader, recover)
  77. if err != nil {
  78. err = E.Cause(err, "read rule[", i, "]")
  79. return
  80. }
  81. }
  82. return
  83. }
  84. func Write(writer io.Writer, ruleSet option.PlainRuleSet, generateVersion uint8) error {
  85. _, err := writer.Write(MagicBytes[:])
  86. if err != nil {
  87. return err
  88. }
  89. err = binary.Write(writer, binary.BigEndian, generateVersion)
  90. if err != nil {
  91. return err
  92. }
  93. compressWriter, err := zlib.NewWriterLevel(writer, zlib.BestCompression)
  94. if err != nil {
  95. return err
  96. }
  97. bWriter := bufio.NewWriter(compressWriter)
  98. _, err = varbin.WriteUvarint(bWriter, uint64(len(ruleSet.Rules)))
  99. if err != nil {
  100. return err
  101. }
  102. for _, rule := range ruleSet.Rules {
  103. err = writeRule(bWriter, rule, generateVersion)
  104. if err != nil {
  105. return err
  106. }
  107. }
  108. err = bWriter.Flush()
  109. if err != nil {
  110. return err
  111. }
  112. return compressWriter.Close()
  113. }
  114. func readRule(reader varbin.Reader, recover bool) (rule option.HeadlessRule, err error) {
  115. var ruleType uint8
  116. err = binary.Read(reader, binary.BigEndian, &ruleType)
  117. if err != nil {
  118. return
  119. }
  120. switch ruleType {
  121. case 0:
  122. rule.Type = C.RuleTypeDefault
  123. rule.DefaultOptions, err = readDefaultRule(reader, recover)
  124. case 1:
  125. rule.Type = C.RuleTypeLogical
  126. rule.LogicalOptions, err = readLogicalRule(reader, recover)
  127. default:
  128. err = E.New("unknown rule type: ", ruleType)
  129. }
  130. return
  131. }
  132. func writeRule(writer varbin.Writer, rule option.HeadlessRule, generateVersion uint8) error {
  133. switch rule.Type {
  134. case C.RuleTypeDefault:
  135. return writeDefaultRule(writer, rule.DefaultOptions, generateVersion)
  136. case C.RuleTypeLogical:
  137. return writeLogicalRule(writer, rule.LogicalOptions, generateVersion)
  138. default:
  139. panic("unknown rule type: " + rule.Type)
  140. }
  141. }
  142. func readDefaultRule(reader varbin.Reader, recover bool) (rule option.DefaultHeadlessRule, err error) {
  143. var lastItemType uint8
  144. for {
  145. var itemType uint8
  146. err = binary.Read(reader, binary.BigEndian, &itemType)
  147. if err != nil {
  148. return
  149. }
  150. switch itemType {
  151. case ruleItemQueryType:
  152. var rawQueryType []uint16
  153. rawQueryType, err = readRuleItemUint16(reader)
  154. if err != nil {
  155. return
  156. }
  157. rule.QueryType = common.Map(rawQueryType, func(it uint16) option.DNSQueryType {
  158. return option.DNSQueryType(it)
  159. })
  160. case ruleItemNetwork:
  161. rule.Network, err = readRuleItemString(reader)
  162. case ruleItemDomain:
  163. var matcher *domain.Matcher
  164. matcher, err = domain.ReadMatcher(reader)
  165. if err != nil {
  166. return
  167. }
  168. rule.DomainMatcher = matcher
  169. if recover {
  170. rule.Domain, rule.DomainSuffix = matcher.Dump()
  171. }
  172. case ruleItemDomainKeyword:
  173. rule.DomainKeyword, err = readRuleItemString(reader)
  174. case ruleItemDomainRegex:
  175. rule.DomainRegex, err = readRuleItemString(reader)
  176. case ruleItemSourceIPCIDR:
  177. rule.SourceIPSet, err = readIPSet(reader)
  178. if err != nil {
  179. return
  180. }
  181. if recover {
  182. rule.SourceIPCIDR = common.Map(rule.SourceIPSet.Prefixes(), netip.Prefix.String)
  183. }
  184. case ruleItemIPCIDR:
  185. rule.IPSet, err = readIPSet(reader)
  186. if err != nil {
  187. return
  188. }
  189. if recover {
  190. rule.IPCIDR = common.Map(rule.IPSet.Prefixes(), netip.Prefix.String)
  191. }
  192. case ruleItemSourcePort:
  193. rule.SourcePort, err = readRuleItemUint16(reader)
  194. case ruleItemSourcePortRange:
  195. rule.SourcePortRange, err = readRuleItemString(reader)
  196. case ruleItemPort:
  197. rule.Port, err = readRuleItemUint16(reader)
  198. case ruleItemPortRange:
  199. rule.PortRange, err = readRuleItemString(reader)
  200. case ruleItemProcessName:
  201. rule.ProcessName, err = readRuleItemString(reader)
  202. case ruleItemProcessPath:
  203. rule.ProcessPath, err = readRuleItemString(reader)
  204. case ruleItemProcessPathRegex:
  205. rule.ProcessPathRegex, err = readRuleItemString(reader)
  206. case ruleItemPackageName:
  207. rule.PackageName, err = readRuleItemString(reader)
  208. case ruleItemWIFISSID:
  209. rule.WIFISSID, err = readRuleItemString(reader)
  210. case ruleItemWIFIBSSID:
  211. rule.WIFIBSSID, err = readRuleItemString(reader)
  212. case ruleItemAdGuardDomain:
  213. var matcher *domain.AdGuardMatcher
  214. matcher, err = domain.ReadAdGuardMatcher(reader)
  215. if err != nil {
  216. return
  217. }
  218. rule.AdGuardDomainMatcher = matcher
  219. if recover {
  220. rule.AdGuardDomain = matcher.Dump()
  221. }
  222. case ruleItemNetworkType:
  223. rule.NetworkType, err = readRuleItemUint8[option.InterfaceType](reader)
  224. case ruleItemNetworkIsExpensive:
  225. rule.NetworkIsExpensive = true
  226. case ruleItemNetworkIsConstrained:
  227. rule.NetworkIsConstrained = true
  228. case ruleItemNetworkInterfaceAddress:
  229. rule.NetworkInterfaceAddress = new(badjson.TypedMap[option.InterfaceType, badoption.Listable[*badoption.Prefixable]])
  230. var size uint64
  231. size, err = binary.ReadUvarint(reader)
  232. if err != nil {
  233. return
  234. }
  235. for i := uint64(0); i < size; i++ {
  236. var key uint8
  237. err = binary.Read(reader, binary.BigEndian, &key)
  238. if err != nil {
  239. return
  240. }
  241. var value []*badoption.Prefixable
  242. var prefixCount uint64
  243. prefixCount, err = binary.ReadUvarint(reader)
  244. if err != nil {
  245. return
  246. }
  247. for j := uint64(0); j < prefixCount; j++ {
  248. var prefix netip.Prefix
  249. prefix, err = readPrefix(reader)
  250. if err != nil {
  251. return
  252. }
  253. value = append(value, common.Ptr(badoption.Prefixable(prefix)))
  254. }
  255. rule.NetworkInterfaceAddress.Put(option.InterfaceType(key), value)
  256. }
  257. case ruleItemDefaultInterfaceAddress:
  258. var value []*badoption.Prefixable
  259. var prefixCount uint64
  260. prefixCount, err = binary.ReadUvarint(reader)
  261. if err != nil {
  262. return
  263. }
  264. for j := uint64(0); j < prefixCount; j++ {
  265. var prefix netip.Prefix
  266. prefix, err = readPrefix(reader)
  267. if err != nil {
  268. return
  269. }
  270. value = append(value, common.Ptr(badoption.Prefixable(prefix)))
  271. }
  272. rule.DefaultInterfaceAddress = value
  273. case ruleItemFinal:
  274. err = binary.Read(reader, binary.BigEndian, &rule.Invert)
  275. return
  276. default:
  277. err = E.New("unknown rule item type: ", itemType, ", last type: ", lastItemType)
  278. }
  279. if err != nil {
  280. return
  281. }
  282. lastItemType = itemType
  283. }
  284. }
  285. func writeDefaultRule(writer varbin.Writer, rule option.DefaultHeadlessRule, generateVersion uint8) error {
  286. err := binary.Write(writer, binary.BigEndian, uint8(0))
  287. if err != nil {
  288. return err
  289. }
  290. if len(rule.QueryType) > 0 {
  291. err = writeRuleItemUint16(writer, ruleItemQueryType, common.Map(rule.QueryType, func(it option.DNSQueryType) uint16 {
  292. return uint16(it)
  293. }))
  294. if err != nil {
  295. return err
  296. }
  297. }
  298. if len(rule.Network) > 0 {
  299. err = writeRuleItemString(writer, ruleItemNetwork, rule.Network)
  300. if err != nil {
  301. return err
  302. }
  303. }
  304. if len(rule.Domain) > 0 || len(rule.DomainSuffix) > 0 {
  305. err = binary.Write(writer, binary.BigEndian, ruleItemDomain)
  306. if err != nil {
  307. return err
  308. }
  309. err = domain.NewMatcher(rule.Domain, rule.DomainSuffix, generateVersion == C.RuleSetVersion1).Write(writer)
  310. if err != nil {
  311. return err
  312. }
  313. }
  314. if len(rule.DomainKeyword) > 0 {
  315. err = writeRuleItemString(writer, ruleItemDomainKeyword, rule.DomainKeyword)
  316. if err != nil {
  317. return err
  318. }
  319. }
  320. if len(rule.DomainRegex) > 0 {
  321. err = writeRuleItemString(writer, ruleItemDomainRegex, rule.DomainRegex)
  322. if err != nil {
  323. return err
  324. }
  325. }
  326. if len(rule.SourceIPCIDR) > 0 {
  327. err = writeRuleItemCIDR(writer, ruleItemSourceIPCIDR, rule.SourceIPCIDR)
  328. if err != nil {
  329. return E.Cause(err, "source_ip_cidr")
  330. }
  331. }
  332. if len(rule.IPCIDR) > 0 {
  333. err = writeRuleItemCIDR(writer, ruleItemIPCIDR, rule.IPCIDR)
  334. if err != nil {
  335. return E.Cause(err, "ipcidr")
  336. }
  337. }
  338. if len(rule.SourcePort) > 0 {
  339. err = writeRuleItemUint16(writer, ruleItemSourcePort, rule.SourcePort)
  340. if err != nil {
  341. return err
  342. }
  343. }
  344. if len(rule.SourcePortRange) > 0 {
  345. err = writeRuleItemString(writer, ruleItemSourcePortRange, rule.SourcePortRange)
  346. if err != nil {
  347. return err
  348. }
  349. }
  350. if len(rule.Port) > 0 {
  351. err = writeRuleItemUint16(writer, ruleItemPort, rule.Port)
  352. if err != nil {
  353. return err
  354. }
  355. }
  356. if len(rule.PortRange) > 0 {
  357. err = writeRuleItemString(writer, ruleItemPortRange, rule.PortRange)
  358. if err != nil {
  359. return err
  360. }
  361. }
  362. if len(rule.ProcessName) > 0 {
  363. err = writeRuleItemString(writer, ruleItemProcessName, rule.ProcessName)
  364. if err != nil {
  365. return err
  366. }
  367. }
  368. if len(rule.ProcessPath) > 0 {
  369. err = writeRuleItemString(writer, ruleItemProcessPath, rule.ProcessPath)
  370. if err != nil {
  371. return err
  372. }
  373. }
  374. if len(rule.ProcessPathRegex) > 0 {
  375. err = writeRuleItemString(writer, ruleItemProcessPathRegex, rule.ProcessPathRegex)
  376. if err != nil {
  377. return err
  378. }
  379. }
  380. if len(rule.PackageName) > 0 {
  381. err = writeRuleItemString(writer, ruleItemPackageName, rule.PackageName)
  382. if err != nil {
  383. return err
  384. }
  385. }
  386. if len(rule.NetworkType) > 0 {
  387. if generateVersion < C.RuleSetVersion3 {
  388. return E.New("`network_type` rule item is only supported in version 3 or later")
  389. }
  390. err = writeRuleItemUint8(writer, ruleItemNetworkType, rule.NetworkType)
  391. if err != nil {
  392. return err
  393. }
  394. }
  395. if rule.NetworkIsExpensive {
  396. if generateVersion < C.RuleSetVersion3 {
  397. return E.New("`network_is_expensive` rule item is only supported in version 3 or later")
  398. }
  399. err = binary.Write(writer, binary.BigEndian, ruleItemNetworkIsExpensive)
  400. if err != nil {
  401. return err
  402. }
  403. }
  404. if rule.NetworkIsConstrained {
  405. if generateVersion < C.RuleSetVersion3 {
  406. return E.New("`network_is_constrained` rule item is only supported in version 3 or later")
  407. }
  408. err = binary.Write(writer, binary.BigEndian, ruleItemNetworkIsConstrained)
  409. if err != nil {
  410. return err
  411. }
  412. }
  413. if rule.NetworkInterfaceAddress != nil && rule.NetworkInterfaceAddress.Size() > 0 {
  414. if generateVersion < C.RuleSetVersion4 {
  415. return E.New("`network_interface_address` rule item is only supported in version 4 or later")
  416. }
  417. err = writer.WriteByte(ruleItemNetworkInterfaceAddress)
  418. if err != nil {
  419. return err
  420. }
  421. _, err = varbin.WriteUvarint(writer, uint64(rule.NetworkInterfaceAddress.Size()))
  422. if err != nil {
  423. return err
  424. }
  425. for _, entry := range rule.NetworkInterfaceAddress.Entries() {
  426. err = binary.Write(writer, binary.BigEndian, uint8(entry.Key.Build()))
  427. if err != nil {
  428. return err
  429. }
  430. _, err = varbin.WriteUvarint(writer, uint64(len(entry.Value)))
  431. if err != nil {
  432. return err
  433. }
  434. for _, rawPrefix := range entry.Value {
  435. err = writePrefix(writer, rawPrefix.Build(netip.Prefix{}))
  436. if err != nil {
  437. return err
  438. }
  439. }
  440. }
  441. }
  442. if len(rule.DefaultInterfaceAddress) > 0 {
  443. if generateVersion < C.RuleSetVersion4 {
  444. return E.New("`default_interface_address` rule item is only supported in version 4 or later")
  445. }
  446. err = writer.WriteByte(ruleItemDefaultInterfaceAddress)
  447. if err != nil {
  448. return err
  449. }
  450. _, err = varbin.WriteUvarint(writer, uint64(len(rule.DefaultInterfaceAddress)))
  451. if err != nil {
  452. return err
  453. }
  454. for _, rawPrefix := range rule.DefaultInterfaceAddress {
  455. err = writePrefix(writer, rawPrefix.Build(netip.Prefix{}))
  456. if err != nil {
  457. return err
  458. }
  459. }
  460. }
  461. if len(rule.WIFISSID) > 0 {
  462. err = writeRuleItemString(writer, ruleItemWIFISSID, rule.WIFISSID)
  463. if err != nil {
  464. return err
  465. }
  466. }
  467. if len(rule.WIFIBSSID) > 0 {
  468. err = writeRuleItemString(writer, ruleItemWIFIBSSID, rule.WIFIBSSID)
  469. if err != nil {
  470. return err
  471. }
  472. }
  473. if len(rule.AdGuardDomain) > 0 {
  474. if generateVersion < C.RuleSetVersion2 {
  475. return E.New("AdGuard rule items is only supported in version 2 or later")
  476. }
  477. err = binary.Write(writer, binary.BigEndian, ruleItemAdGuardDomain)
  478. if err != nil {
  479. return err
  480. }
  481. err = domain.NewAdGuardMatcher(rule.AdGuardDomain).Write(writer)
  482. if err != nil {
  483. return err
  484. }
  485. }
  486. err = binary.Write(writer, binary.BigEndian, ruleItemFinal)
  487. if err != nil {
  488. return err
  489. }
  490. err = binary.Write(writer, binary.BigEndian, rule.Invert)
  491. if err != nil {
  492. return err
  493. }
  494. return nil
  495. }
  496. func readRuleItemString(reader varbin.Reader) ([]string, error) {
  497. length, err := binary.ReadUvarint(reader)
  498. if err != nil {
  499. return nil, err
  500. }
  501. result := make([]string, length)
  502. for i := range result {
  503. strLen, err := binary.ReadUvarint(reader)
  504. if err != nil {
  505. return nil, err
  506. }
  507. buf := make([]byte, strLen)
  508. _, err = io.ReadFull(reader, buf)
  509. if err != nil {
  510. return nil, err
  511. }
  512. result[i] = string(buf)
  513. }
  514. return result, nil
  515. }
  516. func writeRuleItemString(writer varbin.Writer, itemType uint8, value []string) error {
  517. err := writer.WriteByte(itemType)
  518. if err != nil {
  519. return err
  520. }
  521. _, err = varbin.WriteUvarint(writer, uint64(len(value)))
  522. if err != nil {
  523. return err
  524. }
  525. for _, s := range value {
  526. _, err = varbin.WriteUvarint(writer, uint64(len(s)))
  527. if err != nil {
  528. return err
  529. }
  530. _, err = writer.Write([]byte(s))
  531. if err != nil {
  532. return err
  533. }
  534. }
  535. return nil
  536. }
  537. func readRuleItemUint8[E ~uint8](reader varbin.Reader) ([]E, error) {
  538. length, err := binary.ReadUvarint(reader)
  539. if err != nil {
  540. return nil, err
  541. }
  542. result := make([]E, length)
  543. _, err = io.ReadFull(reader, *(*[]byte)(unsafe.Pointer(&result)))
  544. if err != nil {
  545. return nil, err
  546. }
  547. return result, nil
  548. }
  549. func writeRuleItemUint8[E ~uint8](writer varbin.Writer, itemType uint8, value []E) error {
  550. err := writer.WriteByte(itemType)
  551. if err != nil {
  552. return err
  553. }
  554. _, err = varbin.WriteUvarint(writer, uint64(len(value)))
  555. if err != nil {
  556. return err
  557. }
  558. _, err = writer.Write(*(*[]byte)(unsafe.Pointer(&value)))
  559. return err
  560. }
  561. func readRuleItemUint16(reader varbin.Reader) ([]uint16, error) {
  562. length, err := binary.ReadUvarint(reader)
  563. if err != nil {
  564. return nil, err
  565. }
  566. result := make([]uint16, length)
  567. err = binary.Read(reader, binary.BigEndian, result)
  568. if err != nil {
  569. return nil, err
  570. }
  571. return result, nil
  572. }
  573. func writeRuleItemUint16(writer varbin.Writer, itemType uint8, value []uint16) error {
  574. err := writer.WriteByte(itemType)
  575. if err != nil {
  576. return err
  577. }
  578. _, err = varbin.WriteUvarint(writer, uint64(len(value)))
  579. if err != nil {
  580. return err
  581. }
  582. return binary.Write(writer, binary.BigEndian, value)
  583. }
  584. func writeRuleItemCIDR(writer varbin.Writer, itemType uint8, value []string) error {
  585. var builder netipx.IPSetBuilder
  586. for i, prefixString := range value {
  587. prefix, err := netip.ParsePrefix(prefixString)
  588. if err == nil {
  589. builder.AddPrefix(prefix)
  590. continue
  591. }
  592. addr, addrErr := netip.ParseAddr(prefixString)
  593. if addrErr == nil {
  594. builder.Add(addr)
  595. continue
  596. }
  597. return E.Cause(err, "parse [", i, "]")
  598. }
  599. ipSet, err := builder.IPSet()
  600. if err != nil {
  601. return err
  602. }
  603. err = binary.Write(writer, binary.BigEndian, itemType)
  604. if err != nil {
  605. return err
  606. }
  607. return writeIPSet(writer, ipSet)
  608. }
  609. func readLogicalRule(reader varbin.Reader, recovery bool) (logicalRule option.LogicalHeadlessRule, err error) {
  610. mode, err := reader.ReadByte()
  611. if err != nil {
  612. return
  613. }
  614. switch mode {
  615. case 0:
  616. logicalRule.Mode = C.LogicalTypeAnd
  617. case 1:
  618. logicalRule.Mode = C.LogicalTypeOr
  619. default:
  620. err = E.New("unknown logical mode: ", mode)
  621. return
  622. }
  623. length, err := binary.ReadUvarint(reader)
  624. if err != nil {
  625. return
  626. }
  627. logicalRule.Rules = make([]option.HeadlessRule, length)
  628. for i := uint64(0); i < length; i++ {
  629. logicalRule.Rules[i], err = readRule(reader, recovery)
  630. if err != nil {
  631. err = E.Cause(err, "read logical rule [", i, "]")
  632. return
  633. }
  634. }
  635. err = binary.Read(reader, binary.BigEndian, &logicalRule.Invert)
  636. if err != nil {
  637. return
  638. }
  639. return
  640. }
  641. func writeLogicalRule(writer varbin.Writer, logicalRule option.LogicalHeadlessRule, generateVersion uint8) error {
  642. err := binary.Write(writer, binary.BigEndian, uint8(1))
  643. if err != nil {
  644. return err
  645. }
  646. switch logicalRule.Mode {
  647. case C.LogicalTypeAnd:
  648. err = binary.Write(writer, binary.BigEndian, uint8(0))
  649. case C.LogicalTypeOr:
  650. err = binary.Write(writer, binary.BigEndian, uint8(1))
  651. default:
  652. panic("unknown logical mode: " + logicalRule.Mode)
  653. }
  654. if err != nil {
  655. return err
  656. }
  657. _, err = varbin.WriteUvarint(writer, uint64(len(logicalRule.Rules)))
  658. if err != nil {
  659. return err
  660. }
  661. for _, rule := range logicalRule.Rules {
  662. err = writeRule(writer, rule, generateVersion)
  663. if err != nil {
  664. return err
  665. }
  666. }
  667. err = binary.Write(writer, binary.BigEndian, logicalRule.Invert)
  668. if err != nil {
  669. return err
  670. }
  671. return nil
  672. }