Skip to content
This repository has been archived by the owner on Jan 3, 2023. It is now read-only.

Fail to parse(?) decimals with FSharpValue.MakeRecord ONLY in iOS device with Region Spanish/Colombia #893

Closed
mamcx opened this issue Feb 28, 2019 · 8 comments

Comments

@mamcx
Copy link

mamcx commented Feb 28, 2019

This bug not happened on Android, IOS emulator, osx, linux. Only on iOS device, when it have a region different to US/English.

I using reflection for decode Json values, and exactly in FSharpValue.MakeRecord the data of decimals get mangled.

Repro steps

  1. Create a Single View iOS app and fill it with:
namespace test
open System
open UIKit
open Foundation
open Microsoft.FSharp.Reflection

type DocumentRow = {
    doc_id:int32
    doc_kind:string
    doc_code:string
    customer_code:string
    from_code:string option
    username:string
    createdat:DateTime
    updatedat:DateTime
    dueat:DateTime option
    signature:string option
    authorized:string option
    delivery_order:int32
    price:decimal
    cost:decimal
    tax_value:decimal
    discount_value:decimal
    sub_total:decimal
    total:decimal
    status:string
    notes:string option
    syncdata:string option
    version:int32
}

module JSON =
    let fromJSON ty (fields:Reflection.PropertyInfo array) (objs:Map<string, obj>) =
        //printfn "%A" objs
        let values = fields |> Array.map(fun f ->
            let name = f.Name.ToLower()
            if objs.ContainsKey(name) then
                let value = objs.[name] 
                value
            else
                null
        )
        printfn "%A" values
        FSharpValue.MakeRecord(ty, values)

[<Register ("AppDelegate")>]
type AppDelegate () =
    inherit UIApplicationDelegate ()
    override val Window = null with get, set
    override this.FinishedLaunching (app, options) =
        let t = typedefof<DocumentRow>
        let fields = FSharpType.GetRecordFields t

        let data = [
            "doc_id", 1|> box
            "doc_kind", "O"|> box
            "doc_code", "ORD-3-1"|> box
            "customer_code", "70084254_32"|> box
            "from_code", null
            "username", "admin"|> box
            "createdat", DateTime.Now |> box
            "updatedat", DateTime.Now |> box
            "dueat", null
            "signature", null
            "authorized", null
            "delivery_order", 0|> box
            "price", 700M|> box
            "cost", 0M|> box
            "tax_value", 0M|> box
            "discount_value", 0M|> box
            "sub_total", 3500M|> box
            "total", 3500M|> box
            "status", "Draft"|> box
            "notes", null
            "syncdata", null
            "version", null
        ]
        let ob = Map.ofList data
        let r = JSON.fromJSON t fields ob :?> DocumentRow
        printfn "Result = %A" r
        true
  1. Run on emulator, it print in the output windows:
{doc_id = 1;
 doc_kind = "O";
 doc_code = "ORD-3-1";
 customer_code = "70084254_32";
 from_code = None;
 username = "admin";
 createdat = 28/02/2019 6:05:13 p. m.;
 updatedat = 28/02/2019 6:05:13 p. m.;
 dueat = None;
 signature = None;
 authorized = None;
 delivery_order = 0;
 price = 700M;
 cost = 0M;
 tax_value = 0M;
 discount_value = 0M;
 sub_total = 3500M;
 total = 3500M;
 status = "Draft";
 notes = None;
 syncdata = None;
 version = 0;}

this is correct.

  1. Run on a iOS device. I have use a iPhone 6 se, but is reproducible in many others.

It print:

{doc_id = 1;
 doc_kind = "O";
 doc_code = "ORD-3-1";
 customer_code = "70084254_32";
 from_code = None;
 username = "admin";
 createdat = 28/02/2019 6:04:12 p. m.;
 updatedat = 28/02/2019 6:04:12 p. m.;
 dueat = None;
 signature = None;
 authorized = None;
 delivery_order = 0;
 price = 12912720851596686131200M;
 cost = 0M;
 tax_value = 0M;
 discount_value = 0M;
 sub_total = 64563604257983430656000M;
 total = 64564290437145643974656M;
 status = "Draft";
 notes = None;
 syncdata = None;
 version = 0;}

See how all the decimal values get mangled.

Related information

Provide any related information

  • Operating system

iOS 12.1.4

But show in others

  • .NET Runtime, CoreCLR or Mono Version

Visual Studio Community 2017 for Mac
Version 7.8.1 (build 4)
Installation UUID: a339bf84-c405-45c0-8e47-f36faef900a8
GTK+ 2.24.23 (Raleigh theme)
Xamarin.Mac 5.0.0.0 ( / b40230c0)
Mono Framework MDK
Runtime:
Mono 5.16.0.221 (2018-06/b63e5378e38) (64-bit)
Package version: 516000221

NuGet
Version: 4.8.0.5385

Xamarin.iOS
Version: 12.2.1.15 (Visual Studio Community)
Hash: d60abd198
Branch: d15-9
Build date: 2019-02-01 12:23:29-0500

Operating System
Mac OS X 10.14.2
Darwin 18.2.0 Darwin Kernel Version 18.2.0
Mon Nov 12 20:24:46 PST 2018
root:xnu-4903.231.4~2/RELEASE_X86_64 x86_64

  • Indications of severity

This CORRUP THE DATA of the databases of my clients, so is SEVERE.

@cartermp
Copy link
Member

cartermp commented Mar 4, 2019

My guess is this is a mono issue, not an F# issue. The compiler doesn't have specific quirks for locale like this. cc @nosami

@mamcx
Copy link
Author

mamcx commented Mar 5, 2019

Is possible. However it only manifest with FSharpValue.MakeRecord. I start to wonder if is a alignment issue, because I have found some case where some of the fields get back right (I have dozens of structs that serialize decimals values)

@knocte
Copy link
Contributor

knocte commented Mar 5, 2019

If you test it with Windows (MS.NET, not Mono), then you will know if it's a Mono issue or not.

@mamcx
Copy link
Author

mamcx commented Mar 5, 2019

The problem is, will MS.NET run on a iOS device? Because this ONLY happened on a iOS device.

@knocte
Copy link
Contributor

knocte commented Mar 5, 2019

Just test in MS.NET in a normal non-iOS Windows-OS, if you cannot reproduce it, then it's definitely a Mono bug.

@mamcx
Copy link
Author

mamcx commented Mar 5, 2019

Do you read this? At the start say:

This bug not happened on Android, IOS emulator, osx, linux. Only on iOS device, when it have a region different to US/English.

But also, this is FSharp, on the FSharp Api for reflection.

P.D: Maybe is not clear after all. On OSX/Linux it run on .NET core.

@mamcx
Copy link
Author

mamcx commented Mar 5, 2019

Damm, after another heavy rewrite I found it also happened with .NET core and using the dict function.

    //let result = result |> Seq.toArray <--- THIS MAKE IT WORK, but ONLY IF STEP WITH A DEBUGGER!
    result |> dict

@dsyme
Copy link
Contributor

dsyme commented May 16, 2019

Closing out issues in this repo, if necessary please reopen at https://github.com/dotnet/fsharp, which is now the unified repository for F# work

@dsyme dsyme closed this as completed May 16, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants