diff --git a/async_postgres/pg_bytes.nim b/async_postgres/pg_bytes.nim index 540df94..d7682d3 100644 --- a/async_postgres/pg_bytes.nim +++ b/async_postgres/pg_bytes.nim @@ -25,6 +25,56 @@ template writeBE64*(buf: var openArray[byte], pos: int, v: int64) = buf[pos + 6] = byte((v shr 8) and 0xFF) buf[pos + 7] = byte(v and 0xFF) +func toBE16*(v: int16): array[2, byte] {.inline.} = + ## Encode a 16-bit integer as big-endian bytes. + [byte((v shr 8) and 0xFF), byte(v and 0xFF)] + +func toBE32*(v: int32): array[4, byte] {.inline.} = + ## Encode a 32-bit integer as big-endian bytes. + [ + byte((v shr 24) and 0xFF), + byte((v shr 16) and 0xFF), + byte((v shr 8) and 0xFF), + byte(v and 0xFF), + ] + +func toBE64*(v: int64): array[8, byte] {.inline.} = + ## Encode a 64-bit integer as big-endian bytes. + [ + byte((v shr 56) and 0xFF), + byte((v shr 48) and 0xFF), + byte((v shr 40) and 0xFF), + byte((v shr 32) and 0xFF), + byte((v shr 24) and 0xFF), + byte((v shr 16) and 0xFF), + byte((v shr 8) and 0xFF), + byte(v and 0xFF), + ] + +func fromBE16*(data: openArray[byte], offset = 0): int16 {.inline.} = + ## Decode a big-endian 16-bit integer from `data` at `offset`. + int16(data[offset]) shl 8 or int16(data[offset + 1]) + +func fromBE32*(data: openArray[byte], offset = 0): int32 {.inline.} = + ## Decode a big-endian 32-bit integer from `data` at `offset`. + int32(data[offset]) shl 24 or int32(data[offset + 1]) shl 16 or + int32(data[offset + 2]) shl 8 or int32(data[offset + 3]) + +func fromBE64*(data: openArray[byte], offset = 0): int64 {.inline.} = + ## Decode a big-endian 64-bit integer from `data` at `offset`. + int64(data[offset]) shl 56 or int64(data[offset + 1]) shl 48 or + int64(data[offset + 2]) shl 40 or int64(data[offset + 3]) shl 32 or + int64(data[offset + 4]) shl 24 or int64(data[offset + 5]) shl 16 or + int64(data[offset + 6]) shl 8 or int64(data[offset + 7]) + +func decodeFloat32BE*(data: openArray[byte], offset = 0): float32 {.inline.} = + ## Decode a big-endian IEEE-754 32-bit float from `data` at `offset`. + cast[float32](cast[uint32](fromBE32(data, offset))) + +func decodeFloat64BE*(data: openArray[byte], offset = 0): float64 {.inline.} = + ## Decode a big-endian IEEE-754 64-bit float from `data` at `offset`. + cast[float64](cast[uint64](fromBE64(data, offset))) + template writeBytesAt*(dst: var openArray[byte], pos: int, src: openArray[byte]) = ## Copy src bytes into dst starting at pos. No-op when src is empty. if src.len > 0: diff --git a/async_postgres/pg_protocol.nim b/async_postgres/pg_protocol.nim index 29d331a..3fee36a 100644 --- a/async_postgres/pg_protocol.nim +++ b/async_postgres/pg_protocol.nim @@ -319,24 +319,19 @@ func isBinarySafeOid*(oid: int32): bool = # Byte-level helpers -proc encodeInt16*(val: int16): array[2, byte] = +proc encodeInt16*(val: int16): array[2, byte] {.inline.} = ## Encode a 16-bit integer as big-endian bytes. - result[0] = byte((val shr 8) and 0xFF) - result[1] = byte(val and 0xFF) + toBE16(val) -proc encodeInt32*(val: int32): array[4, byte] = +proc encodeInt32*(val: int32): array[4, byte] {.inline.} = ## Encode a 32-bit integer as big-endian bytes. - result[0] = byte((val shr 24) and 0xFF) - result[1] = byte((val shr 16) and 0xFF) - result[2] = byte((val shr 8) and 0xFF) - result[3] = byte(val and 0xFF) + toBE32(val) proc addInt16*(buf: var seq[byte], val: int16) = ## Append a 16-bit integer in big-endian format to the buffer. let oldLen = buf.len buf.setLen(oldLen + 2) - buf[oldLen] = byte((val shr 8) and 0xFF) - buf[oldLen + 1] = byte(val and 0xFF) + buf.writeBE16(oldLen, val) proc addCount16*(buf: var seq[byte], n: int, what: string) = ## Append an Int16 count field, rejecting counts that overflow the wire's @@ -361,10 +356,7 @@ proc addInt32*(buf: var seq[byte], val: int32) = ## Append a 32-bit integer in big-endian format to the buffer. let oldLen = buf.len buf.setLen(oldLen + 4) - buf[oldLen] = byte((val shr 24) and 0xFF) - buf[oldLen + 1] = byte((val shr 16) and 0xFF) - buf[oldLen + 2] = byte((val shr 8) and 0xFF) - buf[oldLen + 3] = byte(val and 0xFF) + buf.writeBE32(oldLen, val) proc addLen32*(buf: var seq[byte], n: int, what: string) = ## Append an Int32 length field, rejecting payloads that overflow the wire's @@ -389,14 +381,7 @@ proc addInt64*(buf: var seq[byte], val: int64) = ## Append a 64-bit integer in big-endian format to the buffer. let oldLen = buf.len buf.setLen(oldLen + 8) - buf[oldLen] = byte((val shr 56) and 0xFF) - buf[oldLen + 1] = byte((val shr 48) and 0xFF) - buf[oldLen + 2] = byte((val shr 40) and 0xFF) - buf[oldLen + 3] = byte((val shr 32) and 0xFF) - buf[oldLen + 4] = byte((val shr 24) and 0xFF) - buf[oldLen + 5] = byte((val shr 16) and 0xFF) - buf[oldLen + 6] = byte((val shr 8) and 0xFF) - buf[oldLen + 7] = byte(val and 0xFF) + buf.writeBE64(oldLen, val) proc patchLen*(buf: var seq[byte], offset: int = 1) = ## Patch the length placeholder at `offset` with buf.len minus the tag byte. @@ -416,10 +401,7 @@ proc patchLen*(buf: var seq[byte], offset: int = 1) = $maxInt32Len, ) let length = int32(buf.high) - buf[offset] = byte((length shr 24) and 0xFF) - buf[offset + 1] = byte((length shr 16) and 0xFF) - buf[offset + 2] = byte((length shr 8) and 0xFF) - buf[offset + 3] = byte(length and 0xFF) + buf.writeBE32(offset, length) proc patchMsgLen*(buf: var seq[byte], msgStart: int) = ## Patch the length field of a message starting at `msgStart`. @@ -440,10 +422,7 @@ proc patchMsgLen*(buf: var seq[byte], msgStart: int) = " exceeds Int32 maximum of " & $maxInt32Len, ) let length = int32(buf.len - msgStart - 1) - buf[msgStart + 1] = byte((length shr 24) and 0xFF) - buf[msgStart + 2] = byte((length shr 16) and 0xFF) - buf[msgStart + 3] = byte((length shr 8) and 0xFF) - buf[msgStart + 4] = byte(length and 0xFF) + buf.writeBE32(msgStart + 1, length) proc addCString*(buf: var seq[byte], s: string) = ## Append a null-terminated C string to the buffer. @@ -462,23 +441,17 @@ proc addCString*(buf: var seq[byte], s: string) = buf.writeBytesAt(oldLen, s.toOpenArrayByte(0, s.high)) buf[oldLen + s.len] = 0'u8 -proc decodeInt16*(buf: openArray[byte], offset: int): int16 = +proc decodeInt16*(buf: openArray[byte], offset: int): int16 {.inline.} = ## Decode a 16-bit integer from big-endian bytes at the given offset. - result = int16(buf[offset]) shl 8 or int16(buf[offset + 1]) + fromBE16(buf, offset) -proc decodeInt32*(buf: openArray[byte], offset: int): int32 = +proc decodeInt32*(buf: openArray[byte], offset: int): int32 {.inline.} = ## Decode a 32-bit integer from big-endian bytes at the given offset. - result = - int32(buf[offset]) shl 24 or int32(buf[offset + 1]) shl 16 or - int32(buf[offset + 2]) shl 8 or int32(buf[offset + 3]) + fromBE32(buf, offset) -proc decodeInt64*(buf: openArray[byte], offset: int): int64 = +proc decodeInt64*(buf: openArray[byte], offset: int): int64 {.inline.} = ## Decode a 64-bit integer from big-endian bytes at the given offset. - result = - int64(buf[offset]) shl 56 or int64(buf[offset + 1]) shl 48 or - int64(buf[offset + 2]) shl 40 or int64(buf[offset + 3]) shl 32 or - int64(buf[offset + 4]) shl 24 or int64(buf[offset + 5]) shl 16 or - int64(buf[offset + 6]) shl 8 or int64(buf[offset + 7]) + fromBE64(buf, offset) proc decodeCString*(buf: openArray[byte], offset: int): (string, int) = ## Decode a null-terminated string at the given offset. Returns (string, bytes consumed). @@ -784,10 +757,7 @@ proc encodeCopyData*(buf: var seq[byte], data: openArray[byte]) = let oldLen = buf.len buf.setLen(oldLen + 5 + data.len) buf[oldLen] = byte('d') - buf[oldLen + 1] = byte((msgLen shr 24) and 0xFF) - buf[oldLen + 2] = byte((msgLen shr 16) and 0xFF) - buf[oldLen + 3] = byte((msgLen shr 8) and 0xFF) - buf[oldLen + 4] = byte(msgLen and 0xFF) + buf.writeBE32(oldLen + 1, msgLen) buf.writeBytesAt(oldLen + 5, data) proc encodeCopyDone*(): seq[byte] = @@ -1132,9 +1102,7 @@ proc parseDataRowInto*(body: openArray[byte], rd: RowData) = rd.buf.setLen(bufBase) raise newException(PgProtocolError, "DataRow: unexpected end of data") # Decode column length from copied buffer (big-endian int32) - let colLen = - int32(rd.buf[pos]) shl 24 or int32(rd.buf[pos + 1]) shl 16 or - int32(rd.buf[pos + 2]) shl 8 or int32(rd.buf[pos + 3]) + let colLen = fromBE32(rd.buf, pos) pos += 4 let ci = cellBase + int(i) * 2 if colLen < -1: diff --git a/async_postgres/pg_types/accessors.nim b/async_postgres/pg_types/accessors.nim index 79f9039..24f827f 100644 --- a/async_postgres/pg_types/accessors.nim +++ b/async_postgres/pg_types/accessors.nim @@ -146,53 +146,35 @@ proc getStr*(row: Row, col: int): string = PgTypeError, "Column " & $col & ": unexpected binary length " & $clen & " for int2", ) - return $int16((uint16(b[off]) shl 8) or uint16(b[off + 1])) + return $fromBE16(b, off) of 23: # int4 if clen != 4: raise newException( PgTypeError, "Column " & $col & ": unexpected binary length " & $clen & " for int4", ) - return $int32( - (uint32(b[off]) shl 24) or (uint32(b[off + 1]) shl 16) or - (uint32(b[off + 2]) shl 8) or uint32(b[off + 3]) - ) + return $fromBE32(b, off) of 20: # int8 if clen != 8: raise newException( PgTypeError, "Column " & $col & ": unexpected binary length " & $clen & " for int8", ) - return $int64( - (uint64(b[off]) shl 56) or (uint64(b[off + 1]) shl 48) or - (uint64(b[off + 2]) shl 40) or (uint64(b[off + 3]) shl 32) or - (uint64(b[off + 4]) shl 24) or (uint64(b[off + 5]) shl 16) or - (uint64(b[off + 6]) shl 8) or uint64(b[off + 7]) - ) + return $fromBE64(b, off) of 700: # float4 if clen != 4: raise newException( PgTypeError, "Column " & $col & ": unexpected binary length " & $clen & " for float4", ) - let bits = uint32( - (uint32(b[off]) shl 24) or (uint32(b[off + 1]) shl 16) or - (uint32(b[off + 2]) shl 8) or uint32(b[off + 3]) - ) - return $cast[float32](bits) + return $decodeFloat32BE(b, off) of 701: # float8 if clen != 8: raise newException( PgTypeError, "Column " & $col & ": unexpected binary length " & $clen & " for float8", ) - let bits = uint64( - (uint64(b[off]) shl 56) or (uint64(b[off + 1]) shl 48) or - (uint64(b[off + 2]) shl 40) or (uint64(b[off + 3]) shl 32) or - (uint64(b[off + 4]) shl 24) or (uint64(b[off + 5]) shl 16) or - (uint64(b[off + 6]) shl 8) or uint64(b[off + 7]) - ) - return $cast[float64](bits) + return $decodeFloat64BE(b, off) of OidNumeric: raiseIfBadNumericBinary(col, clen) return $decodeNumericBinary(b.toOpenArray(off, off + clen - 1)) @@ -207,14 +189,9 @@ proc getInt*(row: Row, col: int): int32 = raise newException(PgTypeError, "Column " & $col & " is NULL") if row.isBinaryCol(col): if clen == 4: - let b = row.data.buf - return int32( - (uint32(b[off]) shl 24) or (uint32(b[off + 1]) shl 16) or - (uint32(b[off + 2]) shl 8) or uint32(b[off + 3]) - ) + return fromBE32(row.data.buf, off) elif clen == 2: - let b = row.data.buf - return int32(int16((uint16(b[off]) shl 8) or uint16(b[off + 1]))) + return int32(fromBE16(row.data.buf, off)) else: raise newException( PgTypeError, @@ -243,8 +220,7 @@ proc getInt16*(row: Row, col: int): int16 = raise newException(PgTypeError, "Column " & $col & " is NULL") if row.isBinaryCol(col): if clen == 2: - let b = row.data.buf - return int16((uint16(b[off]) shl 8) or uint16(b[off + 1])) + return fromBE16(row.data.buf, off) else: raise newException( PgTypeError, @@ -270,24 +246,11 @@ proc getInt64*(row: Row, col: int): int64 = raise newException(PgTypeError, "Column " & $col & " is NULL") if row.isBinaryCol(col): if clen == 8: - let b = row.data.buf - return int64( - (uint64(b[off]) shl 56) or (uint64(b[off + 1]) shl 48) or - (uint64(b[off + 2]) shl 40) or (uint64(b[off + 3]) shl 32) or - (uint64(b[off + 4]) shl 24) or (uint64(b[off + 5]) shl 16) or - (uint64(b[off + 6]) shl 8) or uint64(b[off + 7]) - ) + return fromBE64(row.data.buf, off) elif clen == 4: - let b = row.data.buf - return int64( - int32( - (uint32(b[off]) shl 24) or (uint32(b[off + 1]) shl 16) or - (uint32(b[off + 2]) shl 8) or uint32(b[off + 3]) - ) - ) + return int64(fromBE32(row.data.buf, off)) elif clen == 2: - let b = row.data.buf - return int64(int16((uint16(b[off]) shl 8) or uint16(b[off + 1]))) + return int64(fromBE16(row.data.buf, off)) else: raise newException( PgTypeError, @@ -309,19 +272,9 @@ proc getFloat*(row: Row, col: int): float64 = raise newException(PgTypeError, "Column " & $col & " is NULL") if row.isBinaryCol(col): if clen == 8: - let b = row.data.buf - let bits = - (uint64(b[off]) shl 56) or (uint64(b[off + 1]) shl 48) or - (uint64(b[off + 2]) shl 40) or (uint64(b[off + 3]) shl 32) or - (uint64(b[off + 4]) shl 24) or (uint64(b[off + 5]) shl 16) or - (uint64(b[off + 6]) shl 8) or uint64(b[off + 7]) - return cast[float64](bits) + return decodeFloat64BE(row.data.buf, off) elif clen == 4: - let b = row.data.buf - let bits = - (uint32(b[off]) shl 24) or (uint32(b[off + 1]) shl 16) or - (uint32(b[off + 2]) shl 8) or uint32(b[off + 3]) - return float64(cast[float32](bits)) + return float64(decodeFloat32BE(row.data.buf, off)) else: raise newException( PgTypeError, @@ -341,11 +294,7 @@ proc getFloat32*(row: Row, col: int): float32 = raise newException(PgTypeError, "Column " & $col & " is NULL") if row.isBinaryCol(col): if clen == 4: - let b = row.data.buf - let bits = - (uint32(b[off]) shl 24) or (uint32(b[off + 1]) shl 16) or - (uint32(b[off + 2]) shl 8) or uint32(b[off + 3]) - return cast[float32](bits) + return decodeFloat32BE(row.data.buf, off) else: raise newException( PgTypeError, @@ -1060,15 +1009,9 @@ proc getFloatArray*(row: Row, col: int): seq[float64] = if e.len == -1: raise newException(PgTypeError, "NULL element in float array") if e.len == 4: - result[i] = float64( - cast[float32](cast[uint32](fromBE32( - row.data.buf.toOpenArray(off + e.off, off + e.off + e.len - 1) - ))) - ) + result[i] = float64(decodeFloat32BE(row.data.buf, off + e.off)) elif e.len == 8: - result[i] = cast[float64](cast[uint64](fromBE64( - row.data.buf.toOpenArray(off + e.off, off + e.off + e.len - 1) - ))) + result[i] = decodeFloat64BE(row.data.buf, off + e.off) else: raise newException( PgTypeError, "Unexpected binary element length " & $e.len & " for float array" @@ -1098,9 +1041,7 @@ proc getFloat32Array*(row: Row, col: int): seq[float32] = PgTypeError, "Unexpected binary element length " & $e.len & " for float32 array", ) - result[i] = cast[float32](cast[uint32](fromBE32( - row.data.buf.toOpenArray(off + e.off, off + e.off + e.len - 1) - ))) + result[i] = decodeFloat32BE(row.data.buf, off + e.off) return let s = row.getStr(col) let elems = parseTextArray(s) @@ -1777,19 +1718,9 @@ proc getFloatArrayElemOpt*(row: Row, col: int): seq[Option[float64]] = if e.len == -1: result[i] = none(float64) elif e.len == 4: - result[i] = some( - float64( - cast[float32](cast[uint32](fromBE32( - row.data.buf.toOpenArray(off + e.off, off + e.off + e.len - 1) - ))) - ) - ) + result[i] = some(float64(decodeFloat32BE(row.data.buf, off + e.off))) elif e.len == 8: - result[i] = some( - cast[float64](cast[uint64](fromBE64( - row.data.buf.toOpenArray(off + e.off, off + e.off + e.len - 1) - ))) - ) + result[i] = some(decodeFloat64BE(row.data.buf, off + e.off)) else: raise newException( PgTypeError, "Unexpected binary element length " & $e.len & " for float array" @@ -1819,11 +1750,7 @@ proc getFloat32ArrayElemOpt*(row: Row, col: int): seq[Option[float32]] = "Unexpected binary element length " & $e.len & " for float32 array", ) else: - result[i] = some( - cast[float32](cast[uint32](fromBE32( - row.data.buf.toOpenArray(off + e.off, off + e.off + e.len - 1) - ))) - ) + result[i] = some(decodeFloat32BE(row.data.buf, off + e.off)) return let s = row.getStr(col) for e in parseTextArray(s): @@ -1949,14 +1876,14 @@ proc decodePgArrayElement*( ): float32 {.inline.} = if buf.len != 4: raise newException(PgTypeError, "float4 array element: bad length " & $buf.len) - cast[float32](cast[uint32](fromBE32(buf))) + decodeFloat32BE(buf) proc decodePgArrayElement*( _: typedesc[float64], buf: openArray[byte] ): float64 {.inline.} = if buf.len != 8: raise newException(PgTypeError, "float8 array element: bad length " & $buf.len) - cast[float64](cast[uint64](fromBE64(buf))) + decodeFloat64BE(buf) proc decodePgArrayElement*(_: typedesc[bool], buf: openArray[byte]): bool {.inline.} = if buf.len != 1: diff --git a/async_postgres/pg_types/core.nim b/async_postgres/pg_types/core.nim index cd141fb..b968c49 100644 --- a/async_postgres/pg_types/core.nim +++ b/async_postgres/pg_types/core.nim @@ -3,6 +3,9 @@ import std/[hashes, math, options, parseutils, sequtils, strutils, tables, net] import ../pg_errors export pg_errors +import ../pg_bytes +export pg_bytes + type RelOff* = distinct int ## Offset relative to the start of a slice that was passed into a binary @@ -1053,49 +1056,7 @@ proc toString*(s: seq[byte]): string = if s.len > 0: copyMem(addr result[0], addr s[0], s.len) -proc toBE16*(v: int16): array[2, byte] = - [byte((v shr 8) and 0xFF), byte(v and 0xFF)] - -proc toBE32*(v: int32): array[4, byte] = - [ - byte((v shr 24) and 0xFF), - byte((v shr 16) and 0xFF), - byte((v shr 8) and 0xFF), - byte(v and 0xFF), - ] - -proc toBE64*(v: int64): array[8, byte] = - [ - byte((v shr 56) and 0xFF), - byte((v shr 48) and 0xFF), - byte((v shr 40) and 0xFF), - byte((v shr 32) and 0xFF), - byte((v shr 24) and 0xFF), - byte((v shr 16) and 0xFF), - byte((v shr 8) and 0xFF), - byte(v and 0xFF), - ] - -proc fromBE16*(data: openArray[byte]): int16 = - ## Decode a 16-bit integer from big-endian bytes. - int16(data[0]) shl 8 or int16(data[1]) - -proc fromBE32*(data: openArray[byte]): int32 = - ## Decode a 32-bit integer from big-endian bytes. - int32(data[0]) shl 24 or int32(data[1]) shl 16 or int32(data[2]) shl 8 or - int32(data[3]) - -proc fromBE64*(data: openArray[byte]): int64 = - ## Decode a 64-bit integer from big-endian bytes. - int64(data[0]) shl 56 or int64(data[1]) shl 48 or int64(data[2]) shl 40 or - int64(data[3]) shl 32 or int64(data[4]) shl 24 or int64(data[5]) shl 16 or - int64(data[6]) shl 8 or int64(data[7]) - -proc decodeFloat64BE*(data: openArray[byte], offset: int = 0): float64 = - ## Decode a big-endian 64-bit float from bytes at the given offset. - let bits = - (uint64(data[offset]) shl 56) or (uint64(data[offset + 1]) shl 48) or - (uint64(data[offset + 2]) shl 40) or (uint64(data[offset + 3]) shl 32) or - (uint64(data[offset + 4]) shl 24) or (uint64(data[offset + 5]) shl 16) or - (uint64(data[offset + 6]) shl 8) or uint64(data[offset + 7]) - cast[float64](bits) +# Big-endian integer/float encode/decode helpers live in ``pg_bytes`` (the +# dependency-free module shared with ``pg_protocol``) and are re-exported above +# via ``export pg_bytes``: ``toBE16/32/64``, ``fromBE16/32/64``, +# ``decodeFloat32BE``/``decodeFloat64BE``. diff --git a/async_postgres/pg_types/decoding.nim b/async_postgres/pg_types/decoding.nim index cba00e2..9f4527b 100644 --- a/async_postgres/pg_types/decoding.nim +++ b/async_postgres/pg_types/decoding.nim @@ -194,20 +194,8 @@ proc decodePointBinary*(data: openArray[byte], off: int): PgPoint = ## Decode a point from 16 bytes at offset. if off < 0 or off + 16 > data.len: raise newException(PgTypeError, "Binary point data truncated at offset " & $off) - let xBits = uint64( - (uint64(data[off]) shl 56) or (uint64(data[off + 1]) shl 48) or - (uint64(data[off + 2]) shl 40) or (uint64(data[off + 3]) shl 32) or - (uint64(data[off + 4]) shl 24) or (uint64(data[off + 5]) shl 16) or - (uint64(data[off + 6]) shl 8) or uint64(data[off + 7]) - ) - let yBits = uint64( - (uint64(data[off + 8]) shl 56) or (uint64(data[off + 9]) shl 48) or - (uint64(data[off + 10]) shl 40) or (uint64(data[off + 11]) shl 32) or - (uint64(data[off + 12]) shl 24) or (uint64(data[off + 13]) shl 16) or - (uint64(data[off + 14]) shl 8) or uint64(data[off + 15]) - ) - result.x = cast[float64](xBits) - result.y = cast[float64](yBits) + result.x = decodeFloat64BE(data, off) + result.y = decodeFloat64BE(data, off + 8) proc decodeBinaryArray*( data: openArray[byte] diff --git a/async_postgres/pg_types/encoding.nim b/async_postgres/pg_types/encoding.nim index d79e201..c125d0a 100644 --- a/async_postgres/pg_types/encoding.nim +++ b/async_postgres/pg_types/encoding.nim @@ -1592,8 +1592,7 @@ proc coerceBinaryParam*(param: PgParam, serverOid: int32): PgParam = # float4 -> float8 if param.oid == OidFloat4 and serverOid == OidFloat8 and data.len == 4: - let f = cast[float32](fromBE32(data)) - let d = float64(f) + let d = float64(decodeFloat32BE(data)) return PgParam(oid: OidFloat8, format: 1, value: some(@(toBE64(cast[int64](d))))) raise newException( diff --git a/async_postgres/pg_types/user_types.nim b/async_postgres/pg_types/user_types.nim index 90e61b0..478ea5d 100644 --- a/async_postgres/pg_types/user_types.nim +++ b/async_postgres/pg_types/user_types.nim @@ -369,9 +369,9 @@ template decodeBinaryField(val, buf: untyped, fOff, fEnd, fLen: int) = elif typeof(val) is (int64 or int): val = typeof(val)(fromBE64(buf.toOpenArray(fOff, fEnd))) elif typeof(val) is float64: - val = cast[float64](cast[uint64](fromBE64(buf.toOpenArray(fOff, fEnd)))) + val = decodeFloat64BE(buf.toOpenArray(fOff, fEnd)) elif typeof(val) is float32: - val = cast[float32](cast[uint32](fromBE32(buf.toOpenArray(fOff, fEnd)))) + val = decodeFloat32BE(buf.toOpenArray(fOff, fEnd)) elif typeof(val) is bool: val = buf[fOff] != 0 else: