UNPKG

@heinlein-video/rrule

Version:

rrule fork. Includes the src/ folder for typescript sourceMaps

107 lines (95 loc) 3.12 kB
import IterResult, { IterArgs } from './iterresult' import { clone, cloneDates } from './dateutil' import { isArray } from './helpers' export type CacheKeys = 'before' | 'after' | 'between' function argsMatch( left: IterArgs[keyof IterArgs] | undefined, right: IterArgs[keyof IterArgs] | undefined ) { if (Array.isArray(left)) { if (!Array.isArray(right)) return false if (left.length !== right.length) return false return left.every((date, i) => date.getTime() === right[i].getTime()) } if (left instanceof Date) { return right instanceof Date && left.getTime() === right.getTime() } return left === right } export class Cache { all: Date[] | Partial<IterArgs> | false = false before: IterArgs[] = [] after: IterArgs[] = [] between: IterArgs[] = [] /** * @param {String} what - all/before/after/between * @param {Array,Date} value - an array of dates, one date, or null * @param {Object?} args - _iter arguments */ public _cacheAdd( what: CacheKeys | 'all', value: Date[] | Date | null, args?: Partial<IterArgs> ) { if (value) { value = value instanceof Date ? clone(value) : cloneDates(value) } if (what === 'all') { this.all = value as Date[] } else { args._value = value this[what].push(args as IterArgs) } } /** * @return false - not in the cache * @return null - cached, but zero occurrences (before/after) * @return Date - cached (before/after) * @return [] - cached, but zero occurrences (all/between) * @return [Date1, DateN] - cached (all/between) */ public _cacheGet( what: CacheKeys | 'all', args?: Partial<IterArgs> ): Date | Date[] | false | null { let cached: Date | Date[] | false | null = false const argsKeys = args ? (Object.keys(args) as (keyof IterArgs)[]) : [] const findCacheDiff = function (item: IterArgs) { for (let i = 0; i < argsKeys.length; i++) { const key = argsKeys[i] if (!argsMatch(args[key], item[key])) { return true } } return false } const cachedObject = this[what] if (what === 'all') { cached = this.all as Date[] } else if (isArray(cachedObject)) { // Let's see whether we've already called the // 'what' method with the same 'args' for (let i = 0; i < cachedObject.length; i++) { const item = cachedObject[i] as IterArgs if (argsKeys.length && findCacheDiff(item)) continue cached = item._value break } } if (!cached && this.all) { // Not in the cache, but we already know all the occurrences, // so we can find the correct dates from the cached ones. const iterResult = new IterResult(what, args) for (let i = 0; i < (this.all as Date[]).length; i++) { if (!iterResult.accept((this.all as Date[])[i])) break } cached = iterResult.getValue() as Date this._cacheAdd(what, cached, args) } return isArray(cached) ? cloneDates(cached) : cached instanceof Date ? clone(cached) : cached } }