diff --git a/samples/F#/JsonFormat.fs b/samples/F#/JsonFormat.fs
new file mode 100644
index 00000000..cf6aac61
--- /dev/null
+++ b/samples/F#/JsonFormat.fs
@@ -0,0 +1,65 @@
+namespace Nessos.FsPickler.Json
+
+ open System
+ open System.IO
+ open System.Text
+
+ open Newtonsoft.Json
+
+ open Nessos.FsPickler
+
+ ///
+ /// Factory methods for the Json serialization format.
+ ///
+ type JsonPickleFormatProvider internal (indent, omitHeader) as self =
+
+ let isCustomSeq isTopLevelSequence =
+ isTopLevelSequence && self.OmitHeader && self.UseCustomTopLevelSequenceSeparator
+
+ let mutable sequenceSeparator = " "
+
+ member val Indent = indent with get,set
+ member val OmitHeader = omitHeader with get,set
+ member val UseCustomTopLevelSequenceSeparator = false with get,set
+
+ member __.SequenceSeparator
+ with get () = sequenceSeparator
+ and set sep =
+ if sep <> null && String.IsNullOrWhiteSpace sep then
+ sequenceSeparator <- sep
+ else
+ invalidArg "SequenceSeparator" "should be non-null whitespace."
+
+ interface ITextPickleFormatProvider with
+ member __.Name = "Json"
+
+ // see discussion : https://github.com/nessos/FsPickler/issues/17
+ member __.DefaultEncoding = new UTF8Encoding(false) :> Encoding
+
+ member __.CreateWriter (stream, encoding, isTopLevelSequence, leaveOpen) =
+#if NET40
+ if leaveOpen then raise <| new NotSupportedException("'leaveOpen' not supported in .NET 40.")
+ let sw = new StreamWriter(stream, encoding)
+#else
+ let sw = new StreamWriter(stream, encoding, 1024, leaveOpen)
+#endif
+ let jw = new JsonTextWriter(sw)
+ new JsonPickleWriter(jw, __.OmitHeader, __.Indent, isCustomSeq isTopLevelSequence, sequenceSeparator, leaveOpen) :> _
+
+ member __.CreateReader (stream, encoding, isTopLevelSequence, leaveOpen) =
+#if NET40
+ if leaveOpen then raise <| new NotSupportedException("'leaveOpen' not supported in .NET 40.")
+ let sr = new StreamReader(stream, encoding)
+#else
+ let sr = new StreamReader(stream, encoding, true, 1024, leaveOpen)
+#endif
+ let jr = new JsonTextReader(sr)
+ new JsonPickleReader(jr, __.OmitHeader, isCustomSeq isTopLevelSequence, leaveOpen) :> _
+
+ member __.CreateWriter (textWriter, isTopLevelSequence, leaveOpen) =
+ let jw = new JsonTextWriter(textWriter)
+ new JsonPickleWriter(jw, __.OmitHeader, __.Indent, isCustomSeq isTopLevelSequence, sequenceSeparator, leaveOpen) :> _
+
+ member __.CreateReader (textReader, isTopLevelSequence, leaveOpen) =
+ let jr = new JsonTextReader(textReader)
+ new JsonPickleReader(jr, __.OmitHeader, isCustomSeq isTopLevelSequence, leaveOpen) :> _
\ No newline at end of file
diff --git a/samples/F#/JsonReader.fs b/samples/F#/JsonReader.fs
new file mode 100644
index 00000000..fdd90d3c
--- /dev/null
+++ b/samples/F#/JsonReader.fs
@@ -0,0 +1,202 @@
+namespace Nessos.FsPickler.Json
+
+ open System
+ open System.Collections.Generic
+ open System.Globalization
+ open System.IO
+ open System.Numerics
+ open System.Text
+
+ open Newtonsoft.Json
+
+ open Nessos.FsPickler
+
+ ///
+ /// Json format deserializer
+ ///
+ type internal JsonPickleReader (jsonReader : JsonReader, omitHeader, isTopLevelSequence, leaveOpen) =
+
+ do
+ jsonReader.CloseInput <- not leaveOpen
+ jsonReader.SupportMultipleContent <- isTopLevelSequence
+
+ let isBsonReader = match jsonReader with :? Bson.BsonReader -> true | _ -> false
+
+ let mutable depth = 0
+ let arrayStack = new Stack ()
+ do arrayStack.Push Int32.MinValue
+
+ // do not write tag if omitting header or array element
+ let omitTag () = (omitHeader && depth = 0) || arrayStack.Peek() = depth - 1
+
+ interface IPickleFormatReader with
+
+ member __.BeginReadRoot (tag : string) =
+ do jsonReader.Read() |> ignore
+
+ if omitHeader then () else
+
+ if jsonReader.TokenType <> JsonToken.StartObject then raise <| new FormatException("invalid json root object.")
+ else
+ do jsonReader.MoveNext()
+ let version = jsonReader.ReadPrimitiveAs false "FsPickler"
+ if version <> jsonFormatVersion then
+ let v = Version(version)
+ raise <| new FormatException(sprintf "Invalid FsPickler format version %O." version)
+
+ let sTag = jsonReader.ReadPrimitiveAs false "type"
+ if tag <> sTag then
+ raise <| new InvalidPickleTypeException(tag, sTag)
+
+ member __.EndReadRoot () =
+ if not omitHeader then jsonReader.Read() |> ignore
+
+ member __.BeginReadObject (tag : string) =
+
+ if not <| omitTag () then
+ jsonReader.ReadProperty tag
+ jsonReader.MoveNext ()
+
+ if isTopLevelSequence && depth = 0 then
+ arrayStack.Push depth
+ depth <- depth + 1
+ ObjectFlags.IsSequenceHeader
+
+ else
+ match jsonReader.TokenType with
+ | JsonToken.Null -> ObjectFlags.IsNull
+ | JsonToken.StartArray ->
+ jsonReader.MoveNext()
+ arrayStack.Push depth
+ depth <- depth + 1
+ ObjectFlags.IsSequenceHeader
+
+ | JsonToken.StartObject ->
+ do jsonReader.MoveNext()
+ depth <- depth + 1
+
+ if jsonReader.ValueAs () = "_flags" then
+ jsonReader.MoveNext()
+ let csvFlags = jsonReader.ValueAs()
+ jsonReader.MoveNext()
+ parseFlagCsv csvFlags
+ else
+ ObjectFlags.None
+
+ | token -> raise <| new FormatException(sprintf "expected start of Json object but was '%O'." token)
+
+
+ member __.EndReadObject () =
+ if isTopLevelSequence && depth = 1 then
+ arrayStack.Pop () |> ignore
+ depth <- depth - 1
+ jsonReader.Read() |> ignore
+ else
+ match jsonReader.TokenType with
+ | JsonToken.Null -> ()
+ | JsonToken.EndObject -> depth <- depth - 1
+ | JsonToken.EndArray ->
+ arrayStack.Pop() |> ignore
+ depth <- depth - 1
+
+ | token -> raise <| new FormatException(sprintf "expected end of Json object but was '%O'." token)
+
+ if omitHeader && depth = 0 then ()
+ else jsonReader.Read() |> ignore
+
+ member __.SerializeUnionCaseNames = true
+
+ member __.PreferLengthPrefixInSequences = false
+ member __.ReadNextSequenceElement () =
+ if isTopLevelSequence && depth = 1 then
+ jsonReader.TokenType <> JsonToken.None
+ else
+ jsonReader.TokenType <> JsonToken.EndArray
+
+ member __.ReadCachedObjectId () = jsonReader.ReadPrimitiveAs false "id"
+
+ member __.ReadBoolean tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag
+ member __.ReadByte tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> byte
+ member __.ReadSByte tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> sbyte
+
+ member __.ReadInt16 tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> int16
+ member __.ReadInt32 tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> int
+ member __.ReadInt64 tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag
+
+ member __.ReadUInt16 tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> uint16
+ member __.ReadUInt32 tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> uint32
+ member __.ReadUInt64 tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> uint64
+
+ member __.ReadSingle tag =
+ if not <| omitTag () then
+ jsonReader.ReadProperty tag
+ jsonReader.MoveNext()
+
+ let value =
+ match jsonReader.TokenType with
+ | JsonToken.Float -> jsonReader.ValueAs () |> single
+ | JsonToken.String -> Single.Parse(jsonReader.ValueAs(), CultureInfo.InvariantCulture)
+ | _ -> raise <| new FormatException("not a float.")
+
+ jsonReader.Read() |> ignore
+ value
+
+ member __.ReadDouble tag =
+ if not <| omitTag () then
+ jsonReader.ReadProperty tag
+ jsonReader.MoveNext()
+
+ let value =
+ match jsonReader.TokenType with
+ | JsonToken.Float -> jsonReader.ValueAs ()
+ | JsonToken.String -> Double.Parse(jsonReader.ValueAs(), CultureInfo.InvariantCulture)
+ | _ -> raise <| new FormatException("not a float.")
+
+ jsonReader.Read() |> ignore
+ value
+
+ member __.ReadChar tag = let value = jsonReader.ReadPrimitiveAs (omitTag ()) tag in value.[0]
+ member __.ReadString tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag
+ member __.ReadBigInteger tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> BigInteger.Parse
+
+ member __.ReadGuid tag =
+ if isBsonReader then
+ jsonReader.ReadPrimitiveAs (omitTag ()) tag
+ else
+ jsonReader.ReadPrimitiveAs (omitTag ()) tag |> Guid.Parse
+
+ member __.ReadTimeSpan tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> TimeSpan.Parse
+ member __.ReadDecimal tag = jsonReader.ReadPrimitiveAs (omitTag ()) tag |> decimal
+
+ // BSON spec mandates the use of Unix time;
+ // this has millisecond precision which results in loss of accuracy w.r.t. ticks
+ // since the goal of FsPickler is to offer faithful representations of .NET objects
+ // we choose to override the spec and serialize ticks outright.
+ // see also https://json.codeplex.com/discussions/212067
+ member __.ReadDate tag =
+ if isBsonReader then
+ let ticks = jsonReader.ReadPrimitiveAs (omitTag ()) tag
+ DateTime(ticks)
+ else
+ jsonReader.ReadPrimitiveAs (omitTag ()) tag
+
+ member __.ReadBytes tag =
+ if not <| omitTag () then
+ jsonReader.ReadProperty tag
+ jsonReader.Read() |> ignore
+
+ let bytes =
+ if jsonReader.TokenType = JsonToken.Null then null
+ elif isBsonReader then jsonReader.ValueAs ()
+ else
+ let base64 = jsonReader.ValueAs ()
+ Convert.FromBase64String base64
+
+ jsonReader.Read() |> ignore
+
+ bytes
+
+ member __.IsPrimitiveArraySerializationSupported = false
+ member __.ReadPrimitiveArray _ _ = raise <| new NotImplementedException()
+
+ member __.Dispose () = (jsonReader :> IDisposable).Dispose()
\ No newline at end of file
diff --git a/samples/F#/JsonSerializer.fs b/samples/F#/JsonSerializer.fs
new file mode 100644
index 00000000..15f4929a
--- /dev/null
+++ b/samples/F#/JsonSerializer.fs
@@ -0,0 +1,85 @@
+namespace Nessos.FsPickler.Json
+
+ open System
+
+ open Nessos.FsPickler
+
+ type internal OAttribute = System.Runtime.InteropServices.OptionalAttribute
+ type internal DAttribute = System.Runtime.InteropServices.DefaultParameterValueAttribute
+
+ ///
+ /// Json pickler instance.
+ ///
+ type JsonSerializer =
+ inherit FsPicklerTextSerializer
+
+ val private format : JsonPickleFormatProvider
+
+ ///
+ /// Initializes a new Json pickler instance.
+ ///
+ /// indent out Json pickles.
+ /// omit FsPickler header in Json pickles.
+ /// specify a custom type name converter.
+ new ([] ?indent, [] ?omitHeader, [] ?typeConverter) =
+ let indent = defaultArg indent false
+ let omitHeader = defaultArg omitHeader false
+ let json = new JsonPickleFormatProvider(indent, omitHeader)
+ {
+ inherit FsPicklerTextSerializer(json, ?typeConverter = typeConverter)
+ format = json
+ }
+
+ ///
+ /// Gets or sets whether Json output should be indented.
+ ///
+ member x.Indent
+ with get () = x.format.Indent
+ and set b = x.format.Indent <- b
+
+ ///
+ /// Gets or sets whether FsPickler headers should be ignored in pickle format.
+ ///
+ member x.OmitHeader
+ with get () = x.format.OmitHeader
+ and set b = x.format.OmitHeader <- b
+
+ ///
+ /// Gets or sets a non-null whitespace string that serves as a custom, top-level sequence separator.
+ ///
+ member x.SequenceSeparator
+ with get () = x.format.SequenceSeparator
+ and set sep = x.format.SequenceSeparator <- sep
+
+ ///
+ /// Gets or sets whether top-level sequences should be serialized using the custom separator.
+ ///
+ member x.UseCustomTopLevelSequenceSeparator
+ with get () = x.format.UseCustomTopLevelSequenceSeparator
+ and set e = x.format.UseCustomTopLevelSequenceSeparator <- e
+
+ ///
+ /// BSON pickler instance.
+ ///
+ type BsonSerializer([] ?typeConverter) =
+ inherit FsPicklerSerializer(new BsonPickleFormatProvider(), ?typeConverter = typeConverter)
+
+
+ /// FsPickler static methods.
+ type FsPickler =
+
+ ///
+ /// Initializes a new Json pickler instance.
+ ///
+ /// indent out Json pickles.
+ /// omit FsPickler header in Json pickles.
+ /// specify a custom type name converter.
+ static member CreateJson([] ?indent, [] ?omitHeader, [] ?typeConverter) =
+ new JsonSerializer(?indent = indent, ?omitHeader = omitHeader, ?typeConverter = typeConverter)
+
+ ///
+ /// Initializes a new Bson pickler instance.
+ ///
+ /// specify a custom type name converter.
+ static member CreateBson([] ?typeConverter) =
+ new BsonSerializer(?typeConverter = typeConverter)
\ No newline at end of file
diff --git a/samples/F#/JsonWriter.fs b/samples/F#/JsonWriter.fs
new file mode 100644
index 00000000..bbb6ff24
--- /dev/null
+++ b/samples/F#/JsonWriter.fs
@@ -0,0 +1,142 @@
+namespace Nessos.FsPickler.Json
+
+ open System
+ open System.IO
+ open System.Collections.Generic
+
+ open Newtonsoft.Json
+
+ open Nessos.FsPickler
+
+ ///
+ /// Json format serializer.
+ ///
+ type internal JsonPickleWriter (jsonWriter : JsonWriter, omitHeader, indented, isTopLevelSequence, separator, leaveOpen) =
+
+ do
+ jsonWriter.Formatting <- if indented then Formatting.Indented else Formatting.None
+ jsonWriter.CloseOutput <- not leaveOpen
+
+ let isBsonWriter = match jsonWriter with :? Bson.BsonWriter -> true | _ -> false
+
+ let mutable depth = 0
+ let mutable isTopLevelSequenceHead = false
+ let mutable currentValueIsNull = false
+
+ let arrayStack = new Stack ()
+ do arrayStack.Push Int32.MinValue
+
+ // do not write tag if omitting header or array element
+ let omitTag () = (omitHeader && depth = 0) || arrayStack.Peek() = depth - 1
+
+ interface IPickleFormatWriter with
+
+ member __.BeginWriteRoot (tag : string) =
+ if omitHeader then () else
+
+ jsonWriter.WriteStartObject()
+ writePrimitive jsonWriter false "FsPickler" jsonFormatVersion
+ writePrimitive jsonWriter false "type" tag
+
+ member __.EndWriteRoot () =
+ if not omitHeader then jsonWriter.WriteEnd()
+
+ member __.BeginWriteObject (tag : string) (flags : ObjectFlags) =
+
+ if not <| omitTag () then
+ jsonWriter.WritePropertyName tag
+
+ if flags.HasFlag ObjectFlags.IsNull then
+ currentValueIsNull <- true
+ jsonWriter.WriteNull()
+
+ elif flags.HasFlag ObjectFlags.IsSequenceHeader then
+ if isTopLevelSequence && depth = 0 then
+ isTopLevelSequenceHead <- true
+ else
+ jsonWriter.WriteStartArray()
+
+ arrayStack.Push depth
+ depth <- depth + 1
+ else
+ jsonWriter.WriteStartObject()
+ depth <- depth + 1
+
+ if flags = ObjectFlags.None then ()
+ else
+ let flagCsv = mkFlagCsv flags
+ writePrimitive jsonWriter false "_flags" flagCsv
+
+ member __.EndWriteObject () =
+ if currentValueIsNull then
+ currentValueIsNull <- false
+ else
+ depth <- depth - 1
+ if arrayStack.Peek () = depth then
+ if isTopLevelSequence && depth = 0 then ()
+ else
+ jsonWriter.WriteEndArray()
+
+ arrayStack.Pop () |> ignore
+ else
+ jsonWriter.WriteEndObject()
+
+ member __.SerializeUnionCaseNames = true
+
+ member __.PreferLengthPrefixInSequences = false
+ member __.WriteNextSequenceElement hasNext =
+ if isTopLevelSequence && depth = 1 then
+ if isTopLevelSequenceHead then
+ isTopLevelSequenceHead <- false
+ else
+ jsonWriter.WriteWhitespace separator
+
+ member __.WriteCachedObjectId id = writePrimitive jsonWriter false "id" id
+
+ member __.WriteBoolean (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteByte (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteSByte (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+
+ member __.WriteInt16 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteInt32 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteInt64 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+
+ member __.WriteUInt16 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteUInt32 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteUInt64 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+
+ member __.WriteSingle (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteDouble (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteDecimal (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag (string value)
+
+ member __.WriteChar (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteString (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteBigInteger (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag (string value)
+
+ member __.WriteGuid (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
+ member __.WriteTimeSpan (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag (string value)
+
+ // BSON spec mandates the use of Unix time;
+ // this has millisecond precision which results in loss of accuracy w.r.t. ticks
+ // since the goal of FsPickler is to offer faithful representations of .NET objects
+ // we choose to override the spec and serialize ticks outright.
+ // see also https://json.codeplex.com/discussions/212067
+ member __.WriteDate (tag : string) value =
+ if isBsonWriter then
+ writePrimitive jsonWriter (omitTag ()) tag value.Ticks
+ else
+ writePrimitive jsonWriter (omitTag ()) tag value
+
+ member __.WriteBytes (tag : string) (value : byte []) =
+ if not <| omitTag () then
+ jsonWriter.WritePropertyName tag
+
+ if obj.ReferenceEquals(value, null) then
+ jsonWriter.WriteNull()
+ else
+ jsonWriter.WriteValue value
+
+ member __.IsPrimitiveArraySerializationSupported = false
+ member __.WritePrimitiveArray _ _ = raise <| NotSupportedException()
+
+ member __.Dispose () = jsonWriter.Flush()
\ No newline at end of file
diff --git a/samples/F#/PerformanceTesters.fs b/samples/F#/PerformanceTesters.fs
new file mode 100644
index 00000000..c5eb20d2
--- /dev/null
+++ b/samples/F#/PerformanceTesters.fs
@@ -0,0 +1,68 @@
+namespace Nessos.FsPickler.Tests
+
+ open PerfUtil
+ open PerfUtil.NUnit
+
+ open NUnit.Framework
+
+ open Nessos.FsPickler
+ open Nessos.FsPickler.Json
+
+ []
+ type PerfTester () =
+ inherit NUnitPerf ()
+
+ let tests = PerfTest.OfModuleMarker ()
+
+ override __.PerfTests = tests
+
+
+ type ``Serializer Comparison`` () =
+ inherit PerfTester()
+
+ let fsp = FsPickler.initBinary()
+ let bfs = new BinaryFormatterSerializer() :> Serializer
+ let ndc = new NetDataContractSerializer() :> Serializer
+ let jdn = new JsonDotNetSerializer() :> Serializer
+ let bdn = new JsonDotNetBsonSerializer () :> Serializer
+ let pbn = new ProtoBufSerializer() :> Serializer
+ let ssj = new ServiceStackJsonSerializer() :> Serializer
+ let sst = new ServiceStackTypeSerializer() :> Serializer
+
+ let comparer = new WeightedComparer(spaceFactor = 0.2, leastAcceptableImprovementFactor = 1.)
+ let tester = new ImplementationComparer<_>(fsp, [bfs;ndc;jdn;bdn;pbn;ssj;sst], throwOnError = true, warmup = true, comparer = comparer)
+
+ override __.PerfTester = tester :> _
+
+
+ type ``FsPickler Formats Comparison`` () =
+ inherit PerfTester ()
+
+ let binary = FsPickler.initBinary()
+ let json = FsPickler.initJson()
+ let bson = FsPickler.initBson()
+ let xml = FsPickler.initXml()
+
+ let tester = new ImplementationComparer<_>(binary, [json ; bson; xml], warmup = true, throwOnError = false)
+
+ override __.PerfTester = tester :> _
+
+
+ type ``Past FsPickler Versions Comparison`` () =
+ inherit PerfTester ()
+
+ let persistResults = true
+ let persistenceFile = "fspPerf.xml"
+
+ let fsp = FsPickler.initBinary()
+ let version = typeof.Assembly.GetName().Version
+ let comparer = new WeightedComparer(spaceFactor = 0.2, leastAcceptableImprovementFactor = 0.8)
+ let tester =
+ new PastImplementationComparer(
+ fsp, version, historyFile = persistenceFile, throwOnError = true, warmup = true, comparer = comparer)
+
+ override __.PerfTester = tester :> _
+
+ []
+ member __.Persist() =
+ if persistResults then tester.PersistCurrentResults ()
\ No newline at end of file
diff --git a/samples/F#/PerformanceTests.fs b/samples/F#/PerformanceTests.fs
new file mode 100644
index 00000000..c3d01356
--- /dev/null
+++ b/samples/F#/PerformanceTests.fs
@@ -0,0 +1,207 @@
+namespace Nessos.FsPickler.Tests
+
+ open System
+ open System.Collections.Generic
+
+ open PerfUtil
+
+ open Nessos.FsPickler
+ open Nessos.FsPickler.Tests.Serializer
+ open Nessos.FsPickler.Tests.TestTypes
+
+ module PerformanceTests =
+
+ type Marker = class end
+
+ let guid = Guid.NewGuid()
+
+ []
+ let ``Value: Guid`` s = roundtrip guid s
+
+ let date = DateTime.Now
+
+ []
+ let ``Value: DateTime`` s = roundtrip date s
+
+ []
+ let ``Value: String`` s = roundtrip stringValue s
+
+
+ let boxed = box ([| 1 .. 1000 |], "lorem ipsum")
+
+ []
+ let ``Boxed Object`` s = roundtrip boxed s
+
+ let fsClass = new Class(42, stringValue)
+
+ []
+ let ``Class: Simple F# Class`` s = roundtrip fsClass s
+
+ let serializableClass = new SerializableClass<_>(42, stringValue, [|1..1000|])
+
+ []
+ let ``Class: ISerializable`` s = roundtrip serializableClass s
+
+ let boxedClass = box(Some 42)
+
+ []
+ let ``Subtype Resolution`` s = roundtrip boxedClass s
+
+ let floatArray = Array.init 100000 (fun i -> float i)
+
+ []
+ let ``Array: Float`` s = roundtrip floatArray s
+
+ let intArray = Array.init 100000 id
+
+ []
+ let ``Array: Int`` s = roundtrip intArray s
+
+ let stringArray = Array.init 10000 (fun i -> stringValue + string i)
+
+ []
+ let ``Array: String`` s = roundtrip stringArray s
+
+ let kvarr = [|1..10000|] |> Array.map (fun i -> i, string i)
+
+ []
+ let ``Array: Key-Value Pairs`` s = roundtrip kvarr s
+
+ let duArray = [| for i in 1 .. 10000 -> (Something ("asdasdasdas", i)) |]
+
+ []
+ let ``Array: Discriminated Unions`` s = roundtrip duArray s
+
+ let objArray =
+ [|
+ box 2; box 3; box "hello" ; box <| Some 3; box(2,3) ;
+ box <| new Class(2, stringValue) ; box <| new SerializableClass(2, stringValue, Some 12);
+ box stringValue
+ |]
+
+ []
+ let ``Array: Objects`` s = roundtrip objArray s
+
+
+ let array3D = Array3D.init 100 100 100 (fun i j k -> float (i * j + k))
+
+ []
+ let ``Array: Rank-3 Float`` s = roundtrip array3D s
+
+ let bclDict = dict [ for i in 1 .. 1000 -> (string i, i)]
+
+ []
+ let ``.NET Dictionary`` s = roundtrip bclDict s
+
+ let bclStack = new Stack([for i in 1 .. 1000 -> string i])
+
+ []
+ let ``.NET Stack`` s = roundtrip bclStack s
+
+ let bclList = new List([for i in 1 .. 1000 -> string i, i])
+
+ []
+ let ``.NET List`` s = roundtrip bclList s
+
+ let bclSet = new SortedSet<_>([for i in 1 .. 1000 -> string i])
+
+ []
+ let ``.NET Set`` s = roundtrip bclSet s
+
+ let smallTuple = (1, DateTime.Now,"hello")
+
+ []
+ let ``FSharp: Tuple Small`` s = roundtrip smallTuple s
+
+ let largeTuple = (stringValue, 1, 2, 3, true, "", Some(3.14, [2]), 3, 2, 1, stringValue)
+
+ []
+ let ``FSharp: Tuple Large`` s =
+ roundtrip largeTuple s
+
+ let intList = [1..1000]
+
+ []
+ let ``FSharp: List Int`` s = roundtrip intList s
+
+ let stringList = [ for i in 1 .. 1000 -> stringValue + string i ]
+
+ []
+ let ``FSharp: List String`` s = roundtrip stringList s
+
+ let pairList = [ for i in 1 .. 1000 -> (string i, i) ]
+
+ []
+ let ``FSharp: List Key-Value`` s = roundtrip pairList s
+
+ let nestedLst = let n = [1..1000] in [for _ in 1 .. 100 -> n]
+
+ []
+ let ``FSharp: List Nested`` s = roundtrip nestedLst s
+
+ let union = SomethingElse(stringValue, 42, box (Some 42))
+
+ []
+ let ``FSharp: Union`` s = roundtrip union s
+
+ let record = { Int = 42 ; String = stringValue ; Tuple = (13, "") }
+
+ []
+ let ``FSharp: Record`` s = roundtrip record s
+
+ let peano = int2Peano 100
+
+ []
+ let ``FSharp: Peano Rectype`` s = roundtrip peano s
+
+ let closure = (@) [ Some([1..100], Set.ofList [1..100]) ]
+
+ []
+ let ``FSharp: Curried Function`` s = roundtrip closure s
+
+ let binTree = mkTree 10
+
+ []
+ let ``FSharp: Binary Tree`` s = roundtrip binTree s
+
+ let intSet = [1..1000] |> List.map string |> set
+
+ []
+ let ``FSharp: Set`` s = roundtrip intSet s
+
+ let fsMap = [1..1000] |> Seq.map (fun i -> (string i,i)) |> Map.ofSeq
+
+ []
+ let ``FSharp: Map`` s = roundtrip fsMap s
+
+ let testType = typeof>
+
+ []
+ let ``Reflection: Type`` s = roundtrip testType s
+
+ let quotationSmall = <@ fun x -> pown 2 x @>
+
+ let quotationLarge =
+ <@
+ async {
+ let rec fibAsync n =
+ async {
+ match n with
+ | _ when n < 0 -> return invalidArg "negative" "n"
+ | _ when n < 2 -> return n
+ | n ->
+ let! fn = fibAsync (n-1)
+ let! fnn = fibAsync (n-2)
+ return fn + fnn
+ }
+
+ let! values = [1..100] |> Seq.map fibAsync |> Async.Parallel
+ return Seq.sum values
+ }
+ @>
+
+ []
+ let ``FSharp: Quotation Small`` s = roundtrip quotationSmall s
+
+ []
+ let ``FSharp: Quotation Large`` s = roundtrip quotationLarge s
\ No newline at end of file