aboutsummaryrefslogtreecommitdiff
path: root/internal/caldata/caldata.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-27 12:25:46 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-27 12:25:46 +0200
commit56f3b8161f73c33fe6e25f6461d3f061af427e9e (patch)
tree7abe54aa45b3b4d9e3db0a75564d75c0d44b06ce /internal/caldata/caldata.go
parenta8232892b0ec94f8d077e3730143a09efcac452d (diff)
downloadlectio-56f3b8161f73c33fe6e25f6461d3f061af427e9e.tar.gz
lectio-56f3b8161f73c33fe6e25f6461d3f061af427e9e.zip
feat(caldata): embed + parse the owned universal Roman calendar (initial coverage)
Diffstat (limited to 'internal/caldata/caldata.go')
-rw-r--r--internal/caldata/caldata.go69
1 files changed, 69 insertions, 0 deletions
diff --git a/internal/caldata/caldata.go b/internal/caldata/caldata.go
new file mode 100644
index 0000000..5deb895
--- /dev/null
+++ b/internal/caldata/caldata.go
@@ -0,0 +1,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
+}