aboutsummaryrefslogtreecommitdiff
path: root/internal/caldata/caldata.go
blob: 5deb895c56dbe428a0affd25a1cccebd82a351cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Package caldata embeds and parses lectio's owned universal General Roman
// Calendar data into a calendar.Layer. It imports only internal/ini and
// internal/calendar (types).
package caldata

import (
	_ "embed"
	"fmt"

	"github.com/lukaszkasprzak/lectio/internal/calendar"
	"github.com/lukaszkasprzak/lectio/internal/ini"
)

//go:embed roman-calendar.ini
var romanCalendar []byte

// Universal parses the embedded universal calendar. It panics on a malformed
// embedded file (a build-time bug caught by tests), never at the request layer.
func Universal() calendar.Layer {
	l, err := parse(romanCalendar)
	if err != nil {
		panic(fmt.Sprintf("caldata: embedded roman-calendar.ini invalid: %v", err))
	}
	return l
}

func parse(data []byte) (calendar.Layer, error) {
	secs, err := ini.Parse(data)
	if err != nil {
		return calendar.Layer{}, err
	}
	layer := calendar.Layer{Cels: map[string]calendar.RawCelebration{}}
	for _, s := range secs {
		fields := map[string]string{}
		for _, p := range s.Pairs {
			fields[p.Key] = p.Val
		}
		switch {
		case s.Name == "" && len(fields) == 0:
			continue
		case s.Name == "layer":
			layer.ID, layer.Name, layer.Type = fields["id"], fields["name"], fields["type"]
		default:
			base, variant, isVariant := cutVariant(s.Name)
			rc := layer.Cels[base]
			if rc.Fields == nil {
				rc = calendar.RawCelebration{Fields: map[string]string{}, Variants: map[string]map[string]string{}}
			}
			if isVariant {
				rc.Variants[variant] = fields
			} else {
				for k, v := range fields {
					rc.Fields[k] = v
				}
			}
			layer.Cels[base] = rc
		}
	}
	return layer, nil
}

func cutVariant(name string) (base, variant string, ok bool) {
	for i := 0; i < len(name); i++ {
		if name[i] == '/' {
			return name[:i], name[i+1:], true
		}
	}
	return name, "", false
}