2022-11-16 19:02:14 +00:00
|
|
|
# Extensions for libp2p's protobuf library implementation
|
|
|
|
|
2022-11-04 09:52:27 +00:00
|
|
|
when (NimMajor, NimMinor) < (1, 4):
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
else:
|
|
|
|
{.push raises: [].}
|
2022-06-16 14:04:47 +00:00
|
|
|
|
2024-03-15 23:08:47 +00:00
|
|
|
import std/options, libp2p/protobuf/minprotobuf, libp2p/varint
|
2022-06-16 14:04:47 +00:00
|
|
|
|
2024-03-15 23:08:47 +00:00
|
|
|
export minprotobuf, varint
|
2022-06-16 14:04:47 +00:00
|
|
|
|
2023-02-20 14:03:32 +00:00
|
|
|
## Custom errors
|
|
|
|
|
|
|
|
type
|
|
|
|
ProtobufErrorKind* {.pure.} = enum
|
|
|
|
DecodeFailure
|
|
|
|
MissingRequiredField
|
|
|
|
InvalidLengthField
|
|
|
|
|
|
|
|
ProtobufError* = object
|
|
|
|
case kind*: ProtobufErrorKind
|
|
|
|
of DecodeFailure:
|
|
|
|
error*: minprotobuf.ProtoError
|
|
|
|
of MissingRequiredField, InvalidLengthField:
|
|
|
|
field*: string
|
|
|
|
|
|
|
|
ProtobufResult*[T] = Result[T, ProtobufError]
|
|
|
|
|
|
|
|
converter toProtobufError*(err: minprotobuf.ProtoError): ProtobufError =
|
2024-03-15 23:08:47 +00:00
|
|
|
case err
|
2023-02-20 14:03:32 +00:00
|
|
|
of minprotobuf.ProtoError.RequiredFieldMissing:
|
|
|
|
ProtobufError(kind: ProtobufErrorKind.MissingRequiredField, field: "unknown")
|
|
|
|
else:
|
|
|
|
ProtobufError(kind: ProtobufErrorKind.DecodeFailure, error: err)
|
|
|
|
|
|
|
|
proc missingRequiredField*(T: type ProtobufError, field: string): T =
|
|
|
|
ProtobufError(kind: ProtobufErrorKind.MissingRequiredField, field: field)
|
|
|
|
|
|
|
|
proc invalidLengthField*(T: type ProtobufError, field: string): T =
|
|
|
|
ProtobufError(kind: ProtobufErrorKind.InvalidLengthField, field: field)
|
|
|
|
|
|
|
|
## Extension methods
|
|
|
|
|
2022-06-16 14:04:47 +00:00
|
|
|
proc write3*(proto: var ProtoBuffer, field: int, value: auto) =
|
2022-11-17 19:40:08 +00:00
|
|
|
when value is Option:
|
|
|
|
if value.isSome():
|
|
|
|
proto.write(field, value.get())
|
2022-11-18 17:37:08 +00:00
|
|
|
elif value is bool:
|
|
|
|
proto.write(field, zint(value))
|
2022-11-17 19:40:08 +00:00
|
|
|
else:
|
2022-06-16 14:04:47 +00:00
|
|
|
proto.write(field, value)
|
|
|
|
|
|
|
|
proc finish3*(proto: var ProtoBuffer) =
|
|
|
|
if proto.buffer.len > 0:
|
|
|
|
proto.finish()
|
|
|
|
else:
|
|
|
|
proto.offset = 0
|
|
|
|
|
|
|
|
proc `==`*(a: zint64, b: zint64): bool =
|
2022-09-13 10:37:06 +00:00
|
|
|
int64(a) == int64(b)
|
2023-05-12 16:08:41 +00:00
|
|
|
|
|
|
|
proc `$`*(err: ProtobufError): string =
|
2024-03-15 23:08:47 +00:00
|
|
|
case err.kind
|
2023-05-12 16:08:41 +00:00
|
|
|
of DecodeFailure:
|
2024-03-15 23:08:47 +00:00
|
|
|
case err.error
|
2023-05-12 16:08:41 +00:00
|
|
|
of VarintDecode:
|
|
|
|
return "VarintDecode"
|
|
|
|
of MessageIncomplete:
|
|
|
|
return "MessageIncomplete"
|
|
|
|
of BufferOverflow:
|
|
|
|
return "BufferOverflow"
|
|
|
|
of MessageTooBig:
|
|
|
|
return "MessageTooBig"
|
|
|
|
of BadWireType:
|
|
|
|
return "BadWireType"
|
|
|
|
of IncorrectBlob:
|
|
|
|
return "IncorrectBlob"
|
|
|
|
of RequiredFieldMissing:
|
|
|
|
return "RequiredFieldMissing"
|
|
|
|
of MissingRequiredField:
|
|
|
|
return "MissingRequiredField " & err.field
|
|
|
|
of InvalidLengthField:
|
|
|
|
return "InvalidLengthField " & err.field
|