You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
2.0 KiB
81 lines
2.0 KiB
// Copyright (c) 2022 Proton AG |
|
// |
|
// This file is part of Proton Mail Bridge. |
|
// |
|
// Proton Mail Bridge is free software: you can redistribute it and/or modify |
|
// it under the terms of the GNU General Public License as published by |
|
// the Free Software Foundation, either version 3 of the License, or |
|
// (at your option) any later version. |
|
// |
|
// Proton Mail Bridge is distributed in the hope that it will be useful, |
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
// GNU General Public License for more details. |
|
// |
|
// You should have received a copy of the GNU General Public License |
|
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>. |
|
|
|
package parser |
|
|
|
import "regexp" |
|
|
|
type Visitor struct { |
|
root *Part |
|
rules []*visitorRule |
|
defaultRule VisitorRule |
|
} |
|
|
|
func newVisitor(root *Part, defaultRule VisitorRule) *Visitor { |
|
return &Visitor{ |
|
root: root, |
|
defaultRule: defaultRule, |
|
} |
|
} |
|
|
|
type Visit func(*Part) (interface{}, error) |
|
|
|
type VisitorRule func(*Part, Visit) (interface{}, error) |
|
|
|
type visitorRule struct { |
|
re *regexp.Regexp |
|
fn VisitorRule |
|
} |
|
|
|
// RegisterRule defines what to do when visiting a part whose content type |
|
// matches the given regular expression. |
|
// If a part matches multiple rules, the one registered first will be used. |
|
func (v *Visitor) RegisterRule(contentTypeRegex string, fn VisitorRule) *Visitor { |
|
v.rules = append(v.rules, &visitorRule{ |
|
re: regexp.MustCompile(contentTypeRegex), |
|
fn: fn, |
|
}) |
|
|
|
return v |
|
} |
|
|
|
func (v *Visitor) Visit() (interface{}, error) { |
|
return v.visit(v.root) |
|
} |
|
|
|
func (v *Visitor) visit(p *Part) (interface{}, error) { |
|
t, _, err := p.ContentType() |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
if rule := v.getRuleForContentType(t); rule != nil { |
|
return rule.fn(p, v.visit) |
|
} |
|
|
|
return v.defaultRule(p, v.visit) |
|
} |
|
|
|
func (v *Visitor) getRuleForContentType(contentType string) *visitorRule { |
|
for _, rule := range v.rules { |
|
if rule.re.MatchString(contentType) { |
|
return rule |
|
} |
|
} |
|
|
|
return nil |
|
}
|
|
|