fixes winreg Option[T] decoder

This commit is contained in:
jangko 2020-10-28 16:12:30 +07:00 committed by zah
parent 1e1ba43af2
commit 085d52d3ad
4 changed files with 36 additions and 8 deletions

View File

@ -30,8 +30,6 @@ proc init*(T: type WinregReader,
result.hKey = hKey
result.path = path
template getUnderlyingType*[T](_: Option[T]): untyped = T
proc readValue*[T](r: var WinregReader, value: var T) =
mixin readValue
# TODO: reduce allocation
@ -40,10 +38,11 @@ proc readValue*[T](r: var WinregReader, value: var T) =
let path = constructPath(r.path, r.key)
discard getValue(r.hKey, path, r.key[^1], value)
elif T is Option:
template getUnderlyingType[T](_: Option[T]): untyped = T
type UT = getUnderlyingType(value)
let path = constructPath(r.path, r.key)
var outVal: getUnderlyingType(value)
if getValue(r.hKey, path, r.key[^1], outVal):
value = some(outVal)
if pathExists(r.hKey, path, r.key[^1]):
value = some(r.readValue(UT))
elif T is (seq or array):
when uTypeIsPrimitives(T):
let path = constructPath(r.path, r.key)

View File

@ -1,5 +1,5 @@
import
strutils,
strutils, os,
./types
type
@ -17,6 +17,8 @@ const
RT_QWORD* = 0x00000040
RT_ANY* = 0x0000ffff
MAX_ELEM_SIZE = 16_383'i32
proc regGetValue(hKey: HKEY, lpSubKey, lpValue: cstring,
dwFlags: int32, pdwType: ptr RegType,
pvData: pointer, pcbData: ptr int32): int32 {.
@ -77,6 +79,9 @@ proc getValue*(hKey: HKEY, path, key: string, outVal: var SomePrimitives): bool
call regGetValue(hKey, path, key, RT_QWORD, nil, outVal.addr, valSize.addr)
result = true
proc pathExists*(hKey: HKEY, path, key: string): bool {.inline.} =
result = regGetValue(hKey, path, key, RT_ANY, nil, nil, nil) == 0
proc parseWinregPath*(input: string): (HKEY, string) =
let pos = input.find('\\')
if pos < 0: return

View File

@ -49,7 +49,7 @@ template loadFile*(_: type Winreg,
var reader = unpackArgs(init, [WinregReader, hKey, path, params])
reader.readValue(RecordType)
template saveFile*(Format: type, filename: string, value: auto, params: varargs[untyped]) =
template saveFile*(_: type Winreg, filename: string, value: auto, params: varargs[untyped]) =
mixin init, WriterType, writeValue
# filename should be a Windows Registry path

View File

@ -1,5 +1,5 @@
import
unittest, options,
unittest, options, os,
../confutils/winreg/winreg_serialization,
../confutils/winreg/utils
@ -95,5 +95,29 @@ proc testEncoder() =
check x.antennae.isNone
check x.bumper.get() == "Chromium"
type
ValidIpAddress {.requiresInit.} = object
value: string
TestObject = object
address: Option[ValidIpAddress]
proc readValue(r: var WinregReader, value: var ValidIpAddress) =
r.readValue(value.value)
proc writeValue(w: var WinregWriter, value: ValidIpAddress) =
w.writeValue(value.value)
proc testOptionalFields() =
suite "optional fields test suite":
test "optional field with requiresInit pragma":
var z = TestObject(address: some(ValidIpAddress(value: "1.2.3.4")))
Winreg.saveFile("HKCU" / commonPath, z)
var x = Winreg.loadFile("HKCU" / commonPath, TestObject)
check x.address.isSome
check x.address.get().value == "1.2.3.4"
testUtils()
testEncoder()
testOptionalFields()