Protobuf-net (de)serialization of decimals throws when using custom decimal proto contract (C#/C++ interop) -


say want serialize, deserialize decimal using protobuf-net:

const decimal originaldecimal = 1.6641007661819458m; using (var memorystream = new memorystream()) {     serializer.serialize(memorystream, originaldecimal);     memorystream.position = 0;     var deserializeddecimal = serializer.deserialize<decimal>(memorystream);     assert.areequal(originaldecimal, deserializeddecimal); } 

it works fine. protobuf-net internally uses following representation decimals (cf. bcl.proto):

message decimal {   optional uint64 lo = 1; // first 64 bits of underlying value   optional uint32 hi = 2; // last 32 bis of underlying value   optional sint32 signscale = 3; // number of decimal digits, , sign } 

now define supposedly equivalent proto contract code:

[protocontract] public class mydecimal {     [protomember(1, isrequired = false)]     public ulong lo;      [protomember(2, isrequired = false)]     public uint hi;      [protomember(3, isrequired = false)]     public int signscale; } 

...then can't serialize decimal , mydecimal back, nor serialize mydecimal , decimal back.

from decimal mydecimal:

const decimal originaldecimal = 1.6641007661819458m; using (var memorystream = new memorystream()) {     serializer.serialize(memorystream, originaldecimal);     memorystream.position = 0;      // following line throws invalid wire-type protoexception     serializer.deserialize<mydecimal>(memorystream); } 

from mydecimal decimal:

var mydecimal = new mydecimal {     lo = 0x003b1ee886632642,     hi = 0x00000000,     signscale = 0x00000020, };  using (var memorystream = new memorystream()) {     serializer.serialize(memorystream, mydecimal);     memorystream.position = 0;      // following line throws invalid wire-type protoexception     serializer.deserialize<decimal>(memorystream); } 

am missing here?

i'm working on c++ application needs communicate c# 1 through protocol buffers , can't figure why decimal deserializations fail.

this edge case of "is object? or naked value?". can't just serialize int, say, in protobuf - need wrapper object. naked values, therefore, pretends value field 1 of hypothetical wrapper object. in case of decimal, though, bit tricky - since decimal encoded though object. technically decimal could written naked value... but: looks isn't (it wrapping it) - , doubt idea rectify @ stage.

basically, work lot more reliably if instead of serializing naked value, serialize object has value. also work more efficiently (protobuf-net looks types knows about, naked values fallback scenario). example:

[protocontract] class decimalwrapper {     [protomember(1)]     public decimal value { get; set; } } [protocontract] class mydecimalwrapper {     [protomember(1)]     public mydecimal value { get; set; } } 

if serialize these, 100% interchangeable:

const decimal originaldecimal = 1.6641007661819458m; using (var memorystream = new memorystream()) {     var obj = new decimalwrapper { value = originaldecimal };     serializer.serialize(memorystream, obj);     // or, happens (see text) - equal     // serializer.serialize(memorystream, originaldecimal);      memorystream.position = 0;     var obj2 = serializer.deserialize<mydecimalwrapper>(memorystream);     console.writeline("{0}, {1}, {2}",         obj2.value.lo, obj2.value.hi, obj2.value.signscale);     // ^^^ 16641007661819458, 0, 32      memorystream.setlength(0);     serializer.serialize(memorystream, obj2);     memorystream.position = 0;     var obj3 = serializer.deserialize<decimalwrapper>(memorystream);      bool eq = obj3.value == obj.value; // true } 

actually, because protobuf-net pretends there object, true serialize<decimal> 100% compatible serialize<mydecimalwrapper>, own sanity easier stick simple "always serialize dto instance" approach, rather having think "is dto? or naked value?"


as final thought: if using interop, suggest avoiding decimal, since not defined in protobuf specification, , different platforms have different meaning of "decimal" type. protobuf-net invents meaning, allow protobuf-net round-trip (to itself) wider range of dtos, may awkward parse value arbitrary platform. when working cross-platform , using decimal, recommend considering things double/float, or fixed precision via long/ulong, or maybe string.


Comments

Popular posts from this blog

Change php variable from jquery value using ajax (same page) -

Pull out data related to my apps from Android Play Store and iOS App Store -

How can I fetch data from a web server in an android application? -