mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-21 21:31:14 +07:00
chore: normalize error names
This commit is contained in:
@ -27,7 +27,7 @@ var (
|
||||
systemDns netip.AddrPort
|
||||
systemDnsNextUpdateAfter time.Time
|
||||
|
||||
BadDnsAnsError = fmt.Errorf("bad dns answer")
|
||||
ErrBadDnsAns = fmt.Errorf("bad dns answer")
|
||||
|
||||
BootstrapDns = netip.MustParseAddrPort("208.67.222.222:5353")
|
||||
)
|
||||
@ -107,13 +107,13 @@ func ResolveNetip(ctx context.Context, d netproxy.Dialer, dns netip.AddrPort, ho
|
||||
case dnsmessage.TypeA:
|
||||
a, ok := ans.(*dnsmessage.A)
|
||||
if !ok {
|
||||
return nil, BadDnsAnsError
|
||||
return nil, ErrBadDnsAns
|
||||
}
|
||||
ip, okk = netip.AddrFromSlice(a.A)
|
||||
case dnsmessage.TypeAAAA:
|
||||
a, ok := ans.(*dnsmessage.AAAA)
|
||||
if !ok {
|
||||
return nil, BadDnsAnsError
|
||||
return nil, ErrBadDnsAns
|
||||
}
|
||||
ip, okk = netip.AddrFromSlice(a.AAAA)
|
||||
}
|
||||
@ -137,7 +137,7 @@ func ResolveNS(ctx context.Context, d netproxy.Dialer, dns netip.AddrPort, host
|
||||
}
|
||||
ns, ok := ans.(*dnsmessage.NS)
|
||||
if !ok {
|
||||
return nil, BadDnsAnsError
|
||||
return nil, ErrBadDnsAns
|
||||
}
|
||||
records = append(records, ns.Ns)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var BadUpstreamFormatError = fmt.Errorf("bad upstream format")
|
||||
var ErrBadUpstreamFormat = fmt.Errorf("bad upstream format")
|
||||
|
||||
type Dns struct {
|
||||
log *logrus.Logger
|
||||
@ -55,12 +55,12 @@ func New(dns *config.Dns, opt *NewOption) (s *Dns, err error) {
|
||||
|
||||
tag, link := common.GetTagFromLinkLikePlaintext(string(upstreamRaw))
|
||||
if tag == "" {
|
||||
return nil, fmt.Errorf("%w: '%v' has no tag", BadUpstreamFormatError, upstreamRaw)
|
||||
return nil, fmt.Errorf("%w: '%v' has no tag", ErrBadUpstreamFormat, upstreamRaw)
|
||||
}
|
||||
var u *url.URL
|
||||
u, err = url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", BadUpstreamFormatError, err)
|
||||
return nil, fmt.Errorf("%w: %v", ErrBadUpstreamFormat, err)
|
||||
}
|
||||
r := &UpstreamResolver{
|
||||
Raw: u,
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
FormatError = fmt.Errorf("format error")
|
||||
ErrFormat = fmt.Errorf("format error")
|
||||
)
|
||||
|
||||
type UpstreamScheme string
|
||||
@ -75,7 +75,7 @@ type Upstream struct {
|
||||
func NewUpstream(ctx context.Context, upstream *url.URL, resolverNetwork string) (up *Upstream, err error) {
|
||||
scheme, hostname, port, err := ParseRawUpstream(upstream)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", FormatError, err)
|
||||
return nil, fmt.Errorf("%w: %v", ErrFormat, err)
|
||||
}
|
||||
|
||||
systemDns, err := netutils.SystemDns()
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var NoAliveDialerError = fmt.Errorf("no alive dialer")
|
||||
var ErrNoAliveDialer = fmt.Errorf("no alive dialer")
|
||||
|
||||
type DialerGroup struct {
|
||||
netproxy.Dialer
|
||||
@ -226,14 +226,14 @@ func (d *DialerGroup) MustGetAliveDialerSet(typ *dialer.NetworkType) *dialer.Ali
|
||||
func (g *DialerGroup) Select(networkType *dialer.NetworkType, strictIpVersion bool) (d *dialer.Dialer, latency time.Duration, err error) {
|
||||
policy := g.selectionPolicy
|
||||
d, latency, err = g._select(networkType, policy)
|
||||
if !strictIpVersion && errors.Is(err, NoAliveDialerError) {
|
||||
if !strictIpVersion && errors.Is(err, ErrNoAliveDialer) {
|
||||
networkType.IpVersion = (consts.IpVersion_X - networkType.IpVersion.ToIpVersionType()).ToIpVersionStr()
|
||||
return g._select(networkType, policy)
|
||||
}
|
||||
if err == nil {
|
||||
return d, latency, nil
|
||||
}
|
||||
if errors.Is(err, NoAliveDialerError) && len(g.Dialers) == 1 {
|
||||
if errors.Is(err, ErrNoAliveDialer) && len(g.Dialers) == 1 {
|
||||
// There is only one dialer in this group. Just choose it instead of return error.
|
||||
if d, _, err = g._select(networkType, &DialerSelectionPolicy{
|
||||
Policy: consts.DialerSelectionPolicy_Fixed,
|
||||
@ -256,7 +256,7 @@ func (g *DialerGroup) _select(networkType *dialer.NetworkType, policy *DialerSel
|
||||
d := a.GetRand()
|
||||
if d == nil {
|
||||
// No alive dialer.
|
||||
return nil, time.Hour, NoAliveDialerError
|
||||
return nil, time.Hour, ErrNoAliveDialer
|
||||
}
|
||||
return d, 0, nil
|
||||
|
||||
@ -272,7 +272,7 @@ func (g *DialerGroup) _select(networkType *dialer.NetworkType, policy *DialerSel
|
||||
d, latency := a.GetMinLatency()
|
||||
if d == nil {
|
||||
// No alive dialer.
|
||||
return nil, time.Hour, NoAliveDialerError
|
||||
return nil, time.Hour, ErrNoAliveDialer
|
||||
}
|
||||
return d, latency, nil
|
||||
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
func (s *Sniffer) SniffHttp() (d string, err error) {
|
||||
// First byte should be printable.
|
||||
if s.buf.Len() == 0 || !unicode.IsPrint(rune(s.buf.Bytes()[0])) {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
// Search method.
|
||||
@ -27,10 +27,10 @@ func (s *Sniffer) SniffHttp() (d string, err error) {
|
||||
}
|
||||
method, _, found := bytes.Cut(search, []byte(" "))
|
||||
if !found {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
if !common.IsValidHttpMethod(string(method)) {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
// Now we assume it is an HTTP packet. We should not return NotApplicableError after here.
|
||||
@ -63,5 +63,5 @@ func (s *Sniffer) SniffHttp() (d string, err error) {
|
||||
return strings.TrimSpace(string(value)), nil
|
||||
}
|
||||
}
|
||||
return "", NotFoundError
|
||||
return "", ErrNotFound
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
UnknownFrameTypeError = fmt.Errorf("unknown frame type")
|
||||
OutOfRangeError = fmt.Errorf("index out of range")
|
||||
ErrUnknownFrameType = fmt.Errorf("unknown frame type")
|
||||
ErrOutOfRange = fmt.Errorf("index out of range")
|
||||
)
|
||||
|
||||
const (
|
||||
@ -78,7 +78,7 @@ func ReassembleCryptos(offsets []*CryptoFrameOffset, newPayload []byte) (newOffs
|
||||
|
||||
func ExtractCryptoFrameOffset(remainder []byte, transportOffset int) (offset *CryptoFrameOffset, frameSize int, err error) {
|
||||
if len(remainder) == 0 {
|
||||
return nil, 0, fmt.Errorf("frame has no length: %w", OutOfRangeError)
|
||||
return nil, 0, fmt.Errorf("frame has no length: %w", ErrOutOfRange)
|
||||
}
|
||||
frameType, nextField, err := BigEndianUvarint(remainder)
|
||||
if err != nil {
|
||||
@ -111,7 +111,7 @@ func ExtractCryptoFrameOffset(remainder []byte, transportOffset int) (offset *Cr
|
||||
case Quic_FrameType_ConnectionClose, Quic_FrameType_ConnectionClose2:
|
||||
return nil, 0, fmt.Errorf("connection closed: %w", fs.ErrClosed)
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("%w: %v", UnknownFrameTypeError, frameType)
|
||||
return nil, 0, fmt.Errorf("%w: %v", ErrUnknownFrameType, frameType)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,16 +43,16 @@ func (s *Sniffer) SniffQuic() (d string, err error) {
|
||||
s.quicCryptos, nextBlock, err = sniffQuicBlock(s.quicCryptos, nextBlock)
|
||||
if err != nil {
|
||||
// If block is not a quic block, return it.
|
||||
if errors.Is(err, NotApplicableError) {
|
||||
if errors.Is(err, ErrNotApplicable) {
|
||||
// But if we have found quic block before, correct it.
|
||||
if isQuic {
|
||||
return "", NotFoundError
|
||||
return "", ErrNotFound
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
if errors.Is(err, fs.ErrClosed) {
|
||||
// ConnectionClose sniffed.
|
||||
return "", NotFoundError
|
||||
return "", ErrNotFound
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
@ -67,7 +67,7 @@ func (s *Sniffer) SniffQuic() (d string, err error) {
|
||||
sni, err := extractSniFromTls(quicutils.NewLinearLocator(s.quicCryptos))
|
||||
if err != nil {
|
||||
s.needMore = true
|
||||
return "", NotFoundError
|
||||
return "", ErrNotFound
|
||||
}
|
||||
return sni, nil
|
||||
}
|
||||
@ -78,17 +78,17 @@ func sniffQuicBlock(cryptos []*quicutils.CryptoFrameOffset, buf []byte) (new []*
|
||||
const dstConnIdPos = 6
|
||||
boundary := dstConnIdPos
|
||||
if len(buf) < boundary {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
// Check flag.
|
||||
// Long header: 4 bits masked
|
||||
// High 4 bits are not protected, so we can access QuicFlag_HeaderForm and QuicFlag_LongPacketType without decryption.
|
||||
protectedFlag := buf[0]
|
||||
if ((protectedFlag >> QuicFlag_HeaderForm) & 0b11) != QuicFlag_HeaderForm_LongHeader {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
if ((protectedFlag >> QuicFlag_LongPacketType) & 0b11) != QuicFlag_LongPacketType_Initial {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
|
||||
// Skip version.
|
||||
@ -96,37 +96,37 @@ func sniffQuicBlock(cryptos []*quicutils.CryptoFrameOffset, buf []byte) (new []*
|
||||
destConnIdLength := int(buf[boundary-1])
|
||||
boundary += destConnIdLength + 1 // +1 because next field has 1B length
|
||||
if len(buf) < boundary {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
destConnId := buf[dstConnIdPos : dstConnIdPos+destConnIdLength]
|
||||
|
||||
srcConnIdLength := int(buf[boundary-1])
|
||||
boundary += srcConnIdLength + quicutils.MaxVarintLen64 // The next fields may have quic.MaxVarintLen64 bytes length
|
||||
if len(buf) < boundary {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
tokenLength, n, err := quicutils.BigEndianUvarint(buf[boundary-quicutils.MaxVarintLen64:])
|
||||
if err != nil {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
boundary = boundary - quicutils.MaxVarintLen64 + n // Correct boundary.
|
||||
boundary += int(tokenLength) + quicutils.MaxVarintLen64 // Next fields may have quic.MaxVarintLen64 bytes length
|
||||
if len(buf) < boundary {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
// https://datatracker.ietf.org/doc/html/rfc9000#name-variable-length-integer-enc
|
||||
length, n, err := quicutils.BigEndianUvarint(buf[boundary-quicutils.MaxVarintLen64:])
|
||||
if err != nil {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
boundary = boundary - quicutils.MaxVarintLen64 + n // Correct boundary.
|
||||
blockEnd := boundary + int(length)
|
||||
if len(buf) < blockEnd {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
boundary += quicutils.MaxPacketNumberLength
|
||||
if len(buf) < boundary {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
header := buf[:boundary]
|
||||
// Decrypt protected Packets.
|
||||
@ -144,7 +144,7 @@ func sniffQuicBlock(cryptos []*quicutils.CryptoFrameOffset, buf []byte) (new []*
|
||||
}()
|
||||
plaintext, err := quicutils.DecryptQuic_(header, blockEnd, destConnId)
|
||||
if err != nil {
|
||||
return nil, nil, NotApplicableError
|
||||
return nil, nil, ErrNotApplicable
|
||||
}
|
||||
// Now, we confirm it is exact a quic frame.
|
||||
// After here, we should not return NotApplicableError.
|
||||
@ -153,7 +153,7 @@ func sniffQuicBlock(cryptos []*quicutils.CryptoFrameOffset, buf []byte) (new []*
|
||||
if errors.Is(err, fs.ErrClosed) {
|
||||
return nil, nil, err
|
||||
}
|
||||
return nil, buf[blockEnd:], NotFoundError
|
||||
return nil, buf[blockEnd:], ErrNotFound
|
||||
}
|
||||
return new, buf[blockEnd:], nil
|
||||
}
|
||||
|
@ -70,11 +70,11 @@ func sniffGroup(sniffs ...sniff) (d string, err error) {
|
||||
if err == nil {
|
||||
return d, nil
|
||||
}
|
||||
if err != NotApplicableError {
|
||||
if err != ErrNotApplicable {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
func (s *Sniffer) SniffTcp() (d string, err error) {
|
||||
@ -100,14 +100,14 @@ func (s *Sniffer) SniffTcp() (d string, err error) {
|
||||
return "", s.dataError
|
||||
}
|
||||
case <-s.ctx.Done():
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
} else {
|
||||
close(s.dataReady)
|
||||
}
|
||||
|
||||
if s.buf.Len() == 0 {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
return sniffGroup(
|
||||
@ -125,7 +125,7 @@ func (s *Sniffer) SniffUdp() (d string, err error) {
|
||||
close(s.dataReady)
|
||||
|
||||
if s.buf.Len() == 0 {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
return sniffGroup(
|
||||
|
@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
Error = fmt.Errorf("sniffing error")
|
||||
NotApplicableError = fmt.Errorf("%w: not applicable", Error)
|
||||
NotFoundError = fmt.Errorf("%w: not found", Error)
|
||||
Error = fmt.Errorf("sniffing error")
|
||||
ErrNotApplicable = fmt.Errorf("%w: not applicable", Error)
|
||||
ErrNotFound = fmt.Errorf("%w: not found", Error)
|
||||
)
|
||||
|
||||
func IsSniffingError(err error) bool {
|
||||
|
@ -31,17 +31,17 @@ func (s *Sniffer) SniffTls() (d string, err error) {
|
||||
// https://www.rfc-editor.org/rfc/rfc8446#page-27
|
||||
boundary := 5
|
||||
if s.buf.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
if s.buf.Bytes()[0] != ContentType_HandShake || (!bytes.Equal(s.buf.Bytes()[1:3], Version_Tls1_0) && !bytes.Equal(s.buf.Bytes()[1:3], Version_Tls1_2)) {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
length := int(binary.BigEndian.Uint16(s.buf.Bytes()[3:5]))
|
||||
search := s.buf.Bytes()[5:]
|
||||
if len(search) < length {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
return extractSniFromTls(quicutils.BuiltinBytesLocator(search[:length]))
|
||||
}
|
||||
@ -49,7 +49,7 @@ func (s *Sniffer) SniffTls() (d string, err error) {
|
||||
func extractSniFromTls(search quicutils.Locator) (sni string, err error) {
|
||||
boundary := 39
|
||||
if search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
// Transport Layer Security (TLS) Extensions: Extension Definitions
|
||||
// https://www.rfc-editor.org/rfc/rfc6066#page-5
|
||||
@ -58,17 +58,17 @@ func extractSniFromTls(search quicutils.Locator) (sni string, err error) {
|
||||
return "", err
|
||||
}
|
||||
if b[0] != HandShakeType_Hello {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
// Three bytes length.
|
||||
length2 := (int(b[1]) << 16) + (int(b[2]) << 8) + int(b[3])
|
||||
if search.Len() > length2+4 {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
if !bytes.Equal(b[4:], Version_Tls1_2) {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
// Skip 32 bytes random.
|
||||
@ -79,7 +79,7 @@ func extractSniFromTls(search quicutils.Locator) (sni string, err error) {
|
||||
}
|
||||
boundary += int(sessionIdLength) + 2 // +2 because the next field has 2B length
|
||||
if search.Len() < boundary || search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
b, err = search.Range(boundary-2, boundary)
|
||||
@ -89,7 +89,7 @@ func extractSniFromTls(search quicutils.Locator) (sni string, err error) {
|
||||
cipherSuiteLength := int(binary.BigEndian.Uint16(b))
|
||||
boundary += int(cipherSuiteLength) + 1 // +1 because the next field has 1B length
|
||||
if search.Len() < boundary || search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
compressMethodsLength, err := search.At(boundary - 1)
|
||||
@ -98,7 +98,7 @@ func extractSniFromTls(search quicutils.Locator) (sni string, err error) {
|
||||
}
|
||||
boundary += int(compressMethodsLength) + 2 // +2 because the next field has 2B length
|
||||
if search.Len() < boundary || search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
|
||||
b, err = search.Range(boundary-2, boundary)
|
||||
@ -108,7 +108,7 @@ func extractSniFromTls(search quicutils.Locator) (sni string, err error) {
|
||||
extensionsLength := int(binary.BigEndian.Uint16(b))
|
||||
boundary += extensionsLength + 0 // +0 because our search ends
|
||||
if search.Len() < boundary || search.Len() < boundary {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
// Search SNI
|
||||
extensions, err := search.Slice(boundary-extensionsLength, boundary)
|
||||
@ -123,7 +123,7 @@ func findSniExtension(search quicutils.Locator) (d string, err error) {
|
||||
var b []byte
|
||||
for {
|
||||
if i+4 >= search.Len() {
|
||||
return "", NotFoundError
|
||||
return "", ErrNotFound
|
||||
}
|
||||
b, err = search.Range(i, i+4)
|
||||
if err != nil {
|
||||
@ -134,7 +134,7 @@ func findSniExtension(search quicutils.Locator) (d string, err error) {
|
||||
|
||||
iNextField := i + 4 + extLength
|
||||
if iNextField > search.Len() {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
if typ == TlsExtension_ServerName {
|
||||
b, err = search.Range(i+4, i+6)
|
||||
@ -143,7 +143,7 @@ func findSniExtension(search quicutils.Locator) (d string, err error) {
|
||||
}
|
||||
sniLen := int(binary.BigEndian.Uint16(b))
|
||||
if extLength < sniLen+2 {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
// Search HostName type SNI.
|
||||
for j, indicatorLen := i+6, 0; j+3 <= iNextField; j += indicatorLen {
|
||||
@ -156,7 +156,7 @@ func findSniExtension(search quicutils.Locator) (d string, err error) {
|
||||
continue
|
||||
}
|
||||
if j+3+indicatorLen > iNextField {
|
||||
return "", NotApplicableError
|
||||
return "", ErrNotApplicable
|
||||
}
|
||||
b, err = search.Range(j+3, j+3+indicatorLen)
|
||||
if err != nil {
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
CircularIncludeError = fmt.Errorf("circular include is not allowed")
|
||||
ErrCircularInclude = fmt.Errorf("circular include is not allowed")
|
||||
)
|
||||
|
||||
type Merger struct {
|
||||
@ -51,7 +51,7 @@ func (m *Merger) readEntry(entry string) (err error) {
|
||||
// Check circular include.
|
||||
_, exist := m.entryToSectionMap[entry]
|
||||
if exist {
|
||||
return CircularIncludeError
|
||||
return ErrCircularInclude
|
||||
}
|
||||
|
||||
// Check filename
|
||||
@ -121,7 +121,7 @@ func unsqueezeEntries(patternEntries []string) (unsqueezed []string, err error)
|
||||
func (m *Merger) dfsMerge(entry string, fatherEntry string) (err error) {
|
||||
// Read entry and check circular include.
|
||||
if err = m.readEntry(entry); err != nil {
|
||||
if errors.Is(err, CircularIncludeError) {
|
||||
if errors.Is(err, ErrCircularInclude) {
|
||||
return fmt.Errorf("%w: %v -> %v -> ... -> %v", err, fatherEntry, entry, fatherEntry)
|
||||
}
|
||||
return err
|
||||
|
@ -47,7 +47,7 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
UnsupportedQuestionTypeError = fmt.Errorf("unsupported question type")
|
||||
ErrUnsupportedQuestionType = fmt.Errorf("unsupported question type")
|
||||
)
|
||||
|
||||
var (
|
||||
|
Reference in New Issue
Block a user