aboutsummaryrefslogtreecommitdiffstats
path: root/skate/map.go
diff options
context:
space:
mode:
Diffstat (limited to 'skate/map.go')
-rw-r--r--skate/map.go52
1 files changed, 45 insertions, 7 deletions
diff --git a/skate/map.go b/skate/map.go
index 9d3c98d..d6e37be 100644
--- a/skate/map.go
+++ b/skate/map.go
@@ -25,10 +25,11 @@ type TitleDoc struct {
}
// PartialDoc for docs, that do not have DOI or title. E.g. we found 49701699
-// (NCVY), 36401044 (NCVYU), 29668363 (NCUY), and so on.
+// (NCVY), 36401044 (NCVYU), 29668363 (NCUY), and so on. Some examples: XXX
type PartialDoc struct {
ContainerName string `json:"container_name"`
Contribs []struct {
+ // XXX: Need a way to sensibly compare sets of author names.
RawName string `json:"raw_name"`
} `json:"contribs"`
Volume string `json:"volume"`
@@ -40,17 +41,29 @@ type PartialDoc struct {
// doc). We want fields, but we do not want to bake in TSV into each function.
type Mapper func([]byte) ([][]byte, error)
-// AsTSV serializes the result of a field mapper as TSV. This is a slim adapter,
-// e.g. to parallel.Processor, which expects this function signature.
+// AsTSV serializes the result of a field mapper as TSV. This is a slim
+// adapter, e.g. to parallel.Processor, which expects this function signature.
+// A newline will be appended, if not there already.
func (f Mapper) AsTSV(p []byte) ([]byte, error) {
- fields, err := f(p)
- if err != nil {
+ var (
+ fields [][]byte
+ err error
+ b []byte
+ )
+ if fields, err = f(p); err != nil {
return nil, err
}
- return bytes.Join(fields, bTab), nil
+ if len(fields) == 0 {
+ return nil, nil
+ }
+ b = bytes.Join(fields, bTab)
+ if len(b) > 0 && !bytes.HasSuffix(b, bNewline) {
+ b = append(b, bNewline...)
+ }
+ return b, nil
}
-// WithPrefix adds a given prefix to the first element.
+// WithPrefix is a "mapper middleware", adding a given prefix to the first field.
func WithPrefix(f Mapper, prefix string) Mapper {
return func(p []byte) ([][]byte, error) {
fields, err := f(p)
@@ -65,6 +78,31 @@ func WithPrefix(f Mapper, prefix string) Mapper {
}
}
+// WithBestEffort will not fail on an error.
+func WithBestEffort(f Mapper) Mapper {
+ return func(p []byte) ([][]byte, error) {
+ if fields, err := f(p); err != nil {
+ return nil, nil
+ } else {
+ return fields, err
+ }
+ }
+}
+
+// WithSkipOnEmpty ignores results where the value at a given field is empty.
+func WithSkipOnEmpty(f Mapper, index int) Mapper {
+ return func(p []byte) ([][]byte, error) {
+ fields, err := f(p)
+ if err != nil {
+ return nil, err
+ }
+ if index < len(fields) && len(fields[index]) == 0 {
+ return nil, nil
+ }
+ return fields, err
+ }
+}
+
// NameOf returns name of value, e.g. the name of a function.
func NameOf(f interface{}) string {
v := reflect.ValueOf(f)