Mercurial > games > semicongine
changeset 1470:63364723d460 default tip
fix: make de-/serialization work with all kinds of weird object configurtions
author | sam <sam@basx.dev> |
---|---|
date | Wed, 02 Apr 2025 00:49:02 +0700 |
parents | c69bb7c58cf2 |
children | |
files | semicongine/storage.nim tests/test_storage.nim |
diffstat | 2 files changed, 56 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/storage.nim Tue Apr 01 00:26:49 2025 +0700 +++ b/semicongine/storage.nim Wed Apr 02 00:49:02 2025 +0700 @@ -115,25 +115,43 @@ ) ) -proc writeValue[T: object | tuple](s: Stream, data: T) -proc writeValue[T](s: Stream, value: openArray[T]) +proc writeValue[T](s: Stream, value: T) -proc writeValue[T: SomeOrdinal | SomeFloat](s: Stream, value: T) = +proc writeNumericValue[T](s: Stream, value: T) = s.write(value) -proc writeValue(s: Stream, value: string) = +proc writeStringValue(s: Stream, value: string) = s.write(value.len.int32) s.write(value) -proc writeValue[T](s: Stream, value: openArray[T]) = +proc writeSeqValue[T](s: Stream, value: T) = s.write(value.len.int32) - for v in value: - writeValue(s, v) + for i in 0 ..< value.len: + writeValue(s, value[i]) -proc writeValue[T: object | tuple](s: Stream, data: T) = +proc writeArrayValue[T](s: Stream, value: T) = + s.write(value.len.int32) + for i in 0 ..< value.len: + writeValue(s, value[genericParams(distinctBase(T)).get(0)(i)]) + +proc writeObjectValue[T](s: Stream, data: T) = for field, value in data.fieldPairs(): writeValue(s, value) +proc writeValue[T](s: Stream, value: T) = + when distinctBase(T) is SomeOrdinal or T is SomeFloat: + writeNumericValue[T](s, value) + elif distinctBase(T) is seq: + writeSeqValue[T](s, value) + elif distinctBase(T) is array: + writeArrayValue[T](s, value) + elif distinctBase(T) is string: + writeStringValue(s, value) + elif distinctBase(T) is object or T is tuple: + writeObjectValue[T](s, value) + else: + {.error: "Cannot load type " & $T.} + proc storeWorld*[T]( worldName: string, data: T, table = DEFAULT_WORLD_TABLE_NAME, deleteOld = false ) = @@ -155,45 +173,47 @@ if deleteOld: db.exec(sql(&"""DELETE FROM {table} WHERE key <> ?"""), key) -proc loadNumericValue[T: SomeOrdinal | SomeFloat](s: Stream): T = +proc loadValue[T](s: Stream): T + +proc loadNumericValue[T](s: Stream): T = read(s, result) -proc loadSeqValue[T: seq](s: Stream): T = +proc loadSeqValue[T](s: Stream): T = var len: int32 read(s, len) - for i in 0 ..< len: - var v: elementType(result) - read(s, v) - result.add v + result.setLen(len) + for i in 0 ..< int(len): + # var v: elementType(result) + # read(s, v) + result[i] = loadValue[elementType(result)](s) -proc loadArrayValue[T: array](s: Stream): T = +proc loadArrayValue[T](s: Stream): T = var len: int32 read(s, len) doAssert len == len(result) - for i in 0 ..< len: - read(s, result[i]) + for i in 0 .. high(distinctBase(T)): + read(s, result[genericParams(distinctBase(T)).get(0)(i)]) proc loadStringValue(s: Stream): string = var len: int32 read(s, len) readStr(s, len) -proc loadValue[T](s: Stream): T - -proc loadObjectValue[T: object | tuple](s: Stream): T = +proc loadObjectValue[T](s: Stream): T = for field, value in result.fieldPairs(): - value = loadValue[typeof(value)](s) + {.cast(uncheckedAssign).}: + value = loadValue[typeof(value)](s) proc loadValue[T](s: Stream): T = - when T is SomeOrdinal or T is SomeFloat: + when distinctBase(T) is SomeOrdinal or distinctBase(T) is SomeFloat: loadNumericValue[T](s) - elif T is seq: + elif distinctBase(T) is seq: loadSeqValue[T](s) - elif T is array: + elif distinctBase(T) is array: loadArrayValue[T](s) - elif T is string: + elif distinctBase(T) is string: loadStringValue(s) - elif T is object or T is tuple: + elif distinctBase(T) is object or distinctBase(T) is tuple: loadObjectValue[T](s) else: {.error: "Cannot load type " & $T.}
--- a/tests/test_storage.nim Tue Apr 01 00:26:49 2025 +0700 +++ b/tests/test_storage.nim Wed Apr 02 00:49:02 2025 +0700 @@ -14,9 +14,14 @@ store(storage, KEY, TEST_VALUE) assert storage.load(KEY, 0) == TEST_VALUE +type ID = distinct int +proc `==`(a, b: ID): bool = + `==`(int(a), int(b)) + proc testWorldAPI() = type Obj1 = object value: int + id: ID type Obj2 = object a: string @@ -27,16 +32,18 @@ assert listWorlds().len == 0 - const obj1 = Obj1(value: 42) + const obj1 = Obj1(value: 42, id: ID(1)) "testWorld".storeWorld(obj1) assert listWorlds() == @["testWorld"] assert loadWorld[Obj1]("testWorld") == obj1 const obj2 = Obj2( a: "Hello world", - b: Obj1(value: 20), + b: Obj1(value: 20, id: ID(20)), c: @[1, 2, 3, 4], - d: [Obj1(value: 1), Obj1(value: 2), Obj1(value: 3)], + d: [ + Obj1(value: 1, id: ID(11)), Obj1(value: 2, id: ID(22)), Obj1(value: 3, id: ID(33)) + ], e: true, ) "testWorld".storeWorld(obj2)