(** One calendar layer: a rite's base sanctoral, or a data file of the same shape. Entries are canonically sorted by slug. *) type 'r entry = { date : Date_spec.t; cel : 'r Celebration.t } [@@deriving sexp] type 'r t = { id : string; name : string; entries : 'r entry list } [@@deriving sexp] val empty : id:string -> name:string -> 'r t val of_entries : id:string -> name:string -> 'r entry list -> 'r t val find : 'r t -> Slug.t -> 'r entry option val mem : 'r t -> Slug.t -> bool (** Replaces any entry with the same slug. *) val set : 'r t -> 'r entry -> 'r t val remove : 'r t -> Slug.t -> 'r t (** Date index. Built once per layer, not per year: [Date_spec] dates are year-independent. *) type 'r by_date val index_by_date : 'r t -> 'r by_date val on_date : 'r by_date -> month:int -> day:int -> 'r entry list (** Loads a layer from a sexp file. Parse and validation failures come back as [Error], never as an exception. *) val load : (Sexplib0.Sexp.t -> 'r) -> string -> ('r t, string) result