From 6d60ea15380bdaede26216918e0922edd701f1b5 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sun, 10 Apr 2022 16:17:50 +0200 Subject: [PATCH] Started writing cron expression parser [CI SKIP] --- Makefile | 4 +++ src/cron/cron.v | 27 ++++++++++++++++++- src/cron/expression.v | 55 ++++++++++++++++++++++++++++++++++++++ src/cron/expression_test.v | 5 ++++ src/util.v | 1 + 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/cron/expression.v create mode 100644 src/cron/expression_test.v diff --git a/Makefile b/Makefile index 76ab7b58..9421fb6f 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,10 @@ fmt: vet: $(V) vet -W $(SRC_DIR) +.PHONY: test +test: + $(V) test $(SRC_DIR) + # Build & patch the V compiler .PHONY: v v: v/v diff --git a/src/cron/cron.v b/src/cron/cron.v index ac584eb9..ccb8f9e6 100644 --- a/src/cron/cron.v +++ b/src/cron/cron.v @@ -1,7 +1,32 @@ module cron import git +import datatypes +import time + +struct ScheduledBuild { + repo git.GitRepo + timestamp time.Time +} + +fn (r1 ScheduledBuild) < (r2 ScheduledBuild) bool { + return r1.timestamp < r2.timestamp +} pub fn cron(conf Config) ? { - repos_map := git.get_repos(conf.address, conf.api_key) ? + // mut queue := datatypes.MinHeap{} + // repos_map := git.get_repos(conf.address, conf.api_key) ? + + // for _, repo in repos_map { + // scheduled := ScheduledBuild{ + // repo: repo + // timestamp: 25 + // } + + // queue.insert(scheduled) + // } + + // println(queue) + exp := "10/2 5 *" + println(parse_expression(exp) ?) } diff --git a/src/cron/expression.v b/src/cron/expression.v new file mode 100644 index 00000000..8dae499e --- /dev/null +++ b/src/cron/expression.v @@ -0,0 +1,55 @@ +module cron + +import math + +struct CronExpression { + minutes []u32 + hours []u32 + days []u32 +} + +// parse_range parses a given string into a range of integers, if possible. +fn parse_range(s string, min u32, max u32) ?[]u32 { + mut out := []u32{} + mut start := min + mut interval := u32(1) + + if s != '*' { + exps := s.split('/') + + if exps.len > 1 { + interval = exps[1].u32() + } + // Here, s solely consists of a number, so that's the only value we + // should return. + else{ + return [exps[0].u32()] + } + + if exps[0] != '*' { + start = math.max(exps[0].u32(), min) + } + } + + for start <= max { + out << start + start += interval + } + + return out +} + +// min hour day month day-of-week +fn parse_expression(exp string) ?CronExpression { + parts := exp.split(' ') + + if parts.len != 3 { + return error("Expression must contain 5 space-separated parts.") + } + + return CronExpression{ + minutes: parse_range(parts[0], 0, 59) ? + hours: parse_range(parts[1], 0, 23) ? + days: parse_range(parts[2], 0, 31) ? + } +} diff --git a/src/cron/expression_test.v b/src/cron/expression_test.v new file mode 100644 index 00000000..b3b7422a --- /dev/null +++ b/src/cron/expression_test.v @@ -0,0 +1,5 @@ +module cron + +fn test_parse_star_range() { + assert parse_range('*', 0, 5) == [0, 1, 2, 3, 4, 5] +} diff --git a/src/util.v b/src/util.v index 49c9d223..228f5845 100644 --- a/src/util.v +++ b/src/util.v @@ -44,6 +44,7 @@ pub fn reader_to_file(mut reader io.BufferedReader, length int, path string) ? { for to_write > 0 { // TODO don't just loop infinitely here bytes_written := file.write(buf[bytes_read - to_write..bytes_read]) or { continue } + // file.flush() to_write = to_write - bytes_written }