diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2017-11-01 18:46:56 +0200 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2017-11-01 18:46:56 +0200 |
| commit | fecdbdffdcfcf7b86f7e836ade6157b21c000be0 (patch) | |
| tree | a9586aa1ebe3d3d7df1cec5ed896b4ee989adb81 | |
| parent | 557f9e77cfb0eceb353e582bb73787acbd402b7d (diff) | |
| download | nimrec-fecdbdffdcfcf7b86f7e836ade6157b21c000be0.tar.gz nimrec-fecdbdffdcfcf7b86f7e836ade6157b21c000be0.zip | |
Add simple support for integer fields and integer validation
| -rw-r--r-- | nimrec/recordset.nim | 40 | ||||
| -rw-r--r-- | tests/test.nim | 23 |
2 files changed, 63 insertions, 0 deletions
diff --git a/nimrec/recordset.nim b/nimrec/recordset.nim index 9e6d90c..29422e9 100644 --- a/nimrec/recordset.nim +++ b/nimrec/recordset.nim @@ -2,6 +2,7 @@ import parser import record import utils +import pegs import sequtils import sets import streams @@ -10,15 +11,29 @@ import tables import times type + FieldKind* {.pure.} = enum + Integer + String + + FieldDescriptor* = ref object + kind*: FieldKind + RecordSet* = ref object kind*: string doc*: string + fields*: TableRef[string, FieldDescriptor] mandatory*: HashSet[string] allowed*: HashSet[string] prohibited*: HashSet[string] IntegrityError* = object of Exception +proc addFieldDescriptor(recordSet: RecordSet, name: string): FieldDescriptor = + if name in recordSet.fields: + return recordSet.fields[name] + new(result) + recordSet.fields[name] = result + proc newRecordSet*(record: Record): RecordSet = new(result) @@ -31,6 +46,8 @@ proc newRecordSet*(record: Record): RecordSet = if "%doc" in record: result.doc = record["%doc"] + result.fields = newTable[string, FieldDescriptor]() + for value in values(record, "%mandatory"): for field in split(value): incl(result.mandatory, field) @@ -52,6 +69,17 @@ proc newRecordSet*(record: Record): RecordSet = raise newException(Exception, "a field cannot be allowed and prohibited at the same time") incl(result.allowed, field) + for value in values(record, "%type"): + let parts = split(value) + let label = parts[0] + let kind = parts[1] + let desc = addFieldDescriptor(result, label) + case kind + of "int": desc.kind = FieldKind.Integer + else: desc.kind = FieldKind.String + +let integerPeg = peg"^ '-'? ('0' / ([1-9] \d*)) $" + proc validate*(record: Record, recordSet: RecordSet) = let labels = toSet(toSeq(labels(record))) @@ -68,6 +96,18 @@ proc validate*(record: Record, recordSet: RecordSet) = raise newException(IntegrityError, format("mandatory: $1", mandatoryLabel)) + for label, value in record: + if label notin recordSet.fields: + continue + + let desc = recordSet.fields[label] + + case desc.kind + of FieldKind.Integer: + if not (value =~ integerPeg): + raise newException(IntegrityError, format("integer expected")) + else: discard + iterator recordsInSet*(stream: Stream, kind: string): Record = var currentSet: RecordSet = nil diff --git a/tests/test.nim b/tests/test.nim index 9721fb0..3eda4eb 100644 --- a/tests/test.nim +++ b/tests/test.nim @@ -410,3 +410,26 @@ Address: 10 Foobar Way records = toSeq(records(ss)) expect(Exception): discard newRecordSet(records[0]) + +suite "type basics: integers": + const prologue = """ +%rec: Entry +%type: Value int + +""" + + test "valid integers": + const values = ["0", "1", "123456789", "987654321", "-123456789", + "-987654321", "-0"] + + for value in values: + let data = prologue & "Value: " & value & "\n" + discard toSeq(recordsInSet(newStringStream(data), "Entry")) + + test "invalid integers": + const values = ["0.0", "foobar", "01", "1-"] + + for value in values: + let data = prologue & "Value: " & value & "\n" + expect(Exception): + discard toSeq(recordsInSet(newStringStream(data), "Entry")) |
