parse.go 2.05 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
package chunk

import (
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
)

Kejie Zhang's avatar
Kejie Zhang committed
11 12
var ErrRabinMin = errors.New("the rabin min should not less not 16")

13 14 15
// FromString returns a Splitter depending on the given string:
// it supports "default" (""), "size-{size}", "rabin", "rabin-{blocksize}" and
// "rabin-{min}-{avg}-{max}".
16 17 18
func FromString(r io.Reader, chunker string) (Splitter, error) {
	switch {
	case chunker == "" || chunker == "default":
19
		return DefaultSplitter(r), nil
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

	case strings.HasPrefix(chunker, "size-"):
		sizeStr := strings.Split(chunker, "-")[1]
		size, err := strconv.Atoi(sizeStr)
		if err != nil {
			return nil, err
		}
		return NewSizeSplitter(r, int64(size)), nil

	case strings.HasPrefix(chunker, "rabin"):
		return parseRabinString(r, chunker)

	default:
		return nil, fmt.Errorf("unrecognized chunker option: %s", chunker)
	}
}

func parseRabinString(r io.Reader, chunker string) (Splitter, error) {
	parts := strings.Split(chunker, "-")
	switch len(parts) {
	case 1:
		return NewRabin(r, uint64(DefaultBlockSize)), nil
	case 2:
		size, err := strconv.Atoi(parts[1])
		if err != nil {
			return nil, err
		}
		return NewRabin(r, uint64(size)), nil
	case 4:
		sub := strings.Split(parts[1], ":")
		if len(sub) > 1 && sub[0] != "min" {
			return nil, errors.New("first label must be min")
		}
		min, err := strconv.Atoi(sub[len(sub)-1])
Kejie Zhang's avatar
Kejie Zhang committed
54
		if err != nil {
55 56
			return nil, err
		}
57
		if min < 16 {
Kejie Zhang's avatar
Kejie Zhang committed
58
			return nil, ErrRabinMin
59
		}
60 61
		sub = strings.Split(parts[2], ":")
		if len(sub) > 1 && sub[0] != "avg" {
Kejie Zhang's avatar
Kejie Zhang committed
62
			log.Error("sub == ", sub)
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
			return nil, errors.New("second label must be avg")
		}
		avg, err := strconv.Atoi(sub[len(sub)-1])
		if err != nil {
			return nil, err
		}

		sub = strings.Split(parts[3], ":")
		if len(sub) > 1 && sub[0] != "max" {
			return nil, errors.New("final label must be max")
		}
		max, err := strconv.Atoi(sub[len(sub)-1])
		if err != nil {
			return nil, err
		}

		return NewRabinMinMax(r, uint64(min), uint64(avg), uint64(max)), nil
	default:
		return nil, errors.New("incorrect format (expected 'rabin' 'rabin-[avg]' or 'rabin-[min]-[avg]-[max]'")
	}
}