├── .editorconfig
├── .gitattributes
├── .gitignore
├── CHANGELOG.md
├── Directory.Build.props
├── Directory.Build.targets
├── FsCodec.sln
├── FsCodec.sln.DotSettings
├── LICENSE
├── README.md
├── SECURITY.md
├── azure-pipelines.yml
├── build.proj
├── global.json
├── src
├── FsCodec.Box
│ ├── ByteArray.fs
│ ├── Codec.fs
│ ├── Compression.fs
│ ├── CoreCodec.fs
│ └── FsCodec.Box.fsproj
├── FsCodec.NewtonsoftJson
│ ├── Codec.fs
│ ├── FsCodec.NewtonsoftJson.fsproj
│ ├── OptionConverter.fs
│ ├── Options.fs
│ ├── Pickler.fs
│ ├── Serdes.fs
│ ├── StringIdConverter.fs
│ ├── TypeSafeEnumConverter.fs
│ ├── UnionConverter.fs
│ └── VerbatimUtf8Converter.fs
├── FsCodec.SystemTextJson
│ ├── Codec.fs
│ ├── CodecJsonElement.fs
│ ├── Encoding.fs
│ ├── FsCodec.SystemTextJson.fsproj
│ ├── Interop.fs
│ ├── Options.fs
│ ├── Pickler.fs
│ ├── RejectNullStringConverter.fs
│ ├── Serdes.fs
│ ├── StringIdConverter.fs
│ ├── TypeSafeEnumConverter.fs
│ ├── UnionConverter.fs
│ └── UnionOrTypeSafeEnumConverterFactory.fs
└── FsCodec
│ ├── Codec.fs
│ ├── Encoding.fs
│ ├── FsCodec.fs
│ ├── FsCodec.fsproj
│ ├── StreamId.fs
│ ├── StreamName.fs
│ ├── StringId.fs
│ ├── TypeSafeEnum.fs
│ └── Union.fs
└── tests
├── FsCodec.NewtonsoftJson.Tests
├── Examples.fsx
├── Fixtures.fs
├── FsCodec.NewtonsoftJson.Tests.fsproj
├── PicklerTests.fs
├── SomeNullHandlingTests.fs
├── StreamTests.fs
├── UnionConverterTests.fs
└── VerbatimUtf8ConverterTests.fs
├── FsCodec.SystemTextJson.Tests
├── AutoUnionTests.fs
├── CodecTests.fs
├── EncodingTests.fs
├── Examples.fsx
├── FsCodec.SystemTextJson.Tests.fsproj
├── InteropTests.fs
├── PicklerTests.fs
├── SerdesTests.fs
├── StringIdTests.fs
├── TypeSafeEnumConverterTests.fs
└── UmxInteropTests.fs
└── FsCodec.Tests
├── EncodingTests.fs
├── FsCodec.Tests.fsproj
├── StreamNameTests.fs
└── TypeSafeEnumTests.fs
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 |
4 | [*.fs]
5 | indent_style = space
6 | indent_size = 4
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 | end_of_line = lf
10 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS
2 |
3 | ## Mac
4 |
5 | .DS_Store
6 |
7 | # User-specific files
8 |
9 | # Test results
10 | *.trx
11 |
12 | # Build results
13 | .build/
14 | [Bb]in/
15 | [Oo]bj/
16 |
17 | # Visual Studio 2015+ cache/options directory
18 | .vs/
19 |
20 | # ReSharper is a .NET coding add-in
21 | _ReSharper*/
22 | *.[Rr]e[Ss]harper
23 | *.DotSettings.user
24 |
25 | # NCrunch
26 | _NCrunch_*
27 | .*crunch*.local.xml
28 | nCrunchTemp_*
29 |
30 | # NuGet Packages
31 | *.nupkg
32 | packages.config
33 | # The packages folder can be ignored because of Package Restore
34 | **/packages/*
35 |
36 | # JetBrains Rider
37 | .idea/
38 | *.sln.iml
39 |
40 | # CodeRush
41 | .cr/
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | @jet @moneylion @amjjd @bartelink @eiriktsarpalis and contributors
4 | Jet.com
5 | Extensible F# Event Codec for System.Text.Json and Newtonsoft.Json with versioning tolerant converters
6 | https://github.com/jet/FsCodec
7 | fsharp unionconverter eventcodec JsonPickler JsonIsomorphism UnionConverter json converters typeshape
8 | Apache-2.0
9 | Copyright © 2016-25
10 |
11 |
12 | true
13 | 5
14 | true
15 | true
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MinVerMajor).$(MinVerMinor).$(MinVerPatch)-pr.$(BUILD_PR)
5 | $(PackageVersion).$(MinVerPreRelease)
6 | $(PackageVersion)+$(MinVerBuildMetadata)
7 | $(PackageVersion)
8 |
9 |
10 |
11 |
12 | 0
13 | $(MinVerMajor).$(MinVerMinor).$(MinVerPatch).$(BUILD_ID)
14 |
15 |
16 |
--------------------------------------------------------------------------------
/FsCodec.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsCodec.NewtonsoftJson", "src\FsCodec.NewtonsoftJson\FsCodec.NewtonsoftJson.fsproj", "{ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}"
7 | EndProject
8 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FsCodec.NewtonsoftJson.Tests", "tests\FsCodec.NewtonsoftJson.Tests\FsCodec.NewtonsoftJson.Tests.fsproj", "{F05E2B06-DC4C-4D27-8DA8-370F96364739}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".project", ".project", "{1D0127A7-2F3E-4CEF-90C6-621DA1192875}"
11 | ProjectSection(SolutionItems) = preProject
12 | azure-pipelines.yml = azure-pipelines.yml
13 | build.proj = build.proj
14 | Directory.Build.props = Directory.Build.props
15 | Directory.Build.targets = Directory.Build.targets
16 | global.json = global.json
17 | LICENSE = LICENSE
18 | README.md = README.md
19 | SECURITY.md = SECURITY.md
20 | CHANGELOG.md = CHANGELOG.md
21 | EndProjectSection
22 | EndProject
23 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsCodec", "src\FsCodec\FsCodec.fsproj", "{9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}"
24 | EndProject
25 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsCodec.Tests", "tests\FsCodec.Tests\FsCodec.Tests.fsproj", "{0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}"
26 | EndProject
27 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsCodec.SystemTextJson", "src\FsCodec.SystemTextJson\FsCodec.SystemTextJson.fsproj", "{1A27C90F-85EE-4AE6-A27B-183D0D50F62E}"
28 | EndProject
29 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsCodec.SystemTextJson.Tests", "tests\FsCodec.SystemTextJson.Tests\FsCodec.SystemTextJson.Tests.fsproj", "{5C57C6D6-59AB-426F-9999-FDB90864545E}"
30 | EndProject
31 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsCodec.Box", "src\FsCodec.Box\FsCodec.Box.fsproj", "{93AF284E-BD31-456E-96AC-162C746F9479}"
32 | EndProject
33 | Global
34 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
35 | Debug|Any CPU = Debug|Any CPU
36 | Debug|x64 = Debug|x64
37 | Debug|x86 = Debug|x86
38 | Release|Any CPU = Release|Any CPU
39 | Release|x64 = Release|x64
40 | Release|x86 = Release|x86
41 | EndGlobalSection
42 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
43 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Debug|x64.ActiveCfg = Debug|Any CPU
46 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Debug|x64.Build.0 = Debug|Any CPU
47 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Debug|x86.ActiveCfg = Debug|Any CPU
48 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Debug|x86.Build.0 = Debug|Any CPU
49 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Release|x64.ActiveCfg = Release|Any CPU
52 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Release|x64.Build.0 = Release|Any CPU
53 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Release|x86.ActiveCfg = Release|Any CPU
54 | {ACB412D4-AB3D-4594-BD97-84EA97E2BE7B}.Release|x86.Build.0 = Release|Any CPU
55 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Debug|Any CPU.Build.0 = Debug|Any CPU
57 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Debug|x64.ActiveCfg = Debug|Any CPU
58 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Debug|x64.Build.0 = Debug|Any CPU
59 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Debug|x86.ActiveCfg = Debug|Any CPU
60 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Debug|x86.Build.0 = Debug|Any CPU
61 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Release|Any CPU.ActiveCfg = Release|Any CPU
62 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Release|Any CPU.Build.0 = Release|Any CPU
63 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Release|x64.ActiveCfg = Release|Any CPU
64 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Release|x64.Build.0 = Release|Any CPU
65 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Release|x86.ActiveCfg = Release|Any CPU
66 | {F05E2B06-DC4C-4D27-8DA8-370F96364739}.Release|x86.Build.0 = Release|Any CPU
67 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
68 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Debug|Any CPU.Build.0 = Debug|Any CPU
69 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Debug|x64.ActiveCfg = Debug|Any CPU
70 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Debug|x64.Build.0 = Debug|Any CPU
71 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Debug|x86.ActiveCfg = Debug|Any CPU
72 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Debug|x86.Build.0 = Debug|Any CPU
73 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Release|Any CPU.ActiveCfg = Release|Any CPU
74 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Release|Any CPU.Build.0 = Release|Any CPU
75 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Release|x64.ActiveCfg = Release|Any CPU
76 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Release|x64.Build.0 = Release|Any CPU
77 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Release|x86.ActiveCfg = Release|Any CPU
78 | {9D2A9566-9C80-4AF3-A487-76A9FE8CBE64}.Release|x86.Build.0 = Release|Any CPU
79 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
80 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Debug|Any CPU.Build.0 = Debug|Any CPU
81 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Debug|x64.ActiveCfg = Debug|Any CPU
82 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Debug|x64.Build.0 = Debug|Any CPU
83 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Debug|x86.ActiveCfg = Debug|Any CPU
84 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Debug|x86.Build.0 = Debug|Any CPU
85 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Release|Any CPU.ActiveCfg = Release|Any CPU
86 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Release|Any CPU.Build.0 = Release|Any CPU
87 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Release|x64.ActiveCfg = Release|Any CPU
88 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Release|x64.Build.0 = Release|Any CPU
89 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Release|x86.ActiveCfg = Release|Any CPU
90 | {0A1529E7-8DEF-4B2B-9737-3DB7BD3F1954}.Release|x86.Build.0 = Release|Any CPU
91 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
92 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Debug|Any CPU.Build.0 = Debug|Any CPU
93 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Debug|x64.ActiveCfg = Debug|Any CPU
94 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Debug|x64.Build.0 = Debug|Any CPU
95 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Debug|x86.ActiveCfg = Debug|Any CPU
96 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Debug|x86.Build.0 = Debug|Any CPU
97 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Release|Any CPU.ActiveCfg = Release|Any CPU
98 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Release|Any CPU.Build.0 = Release|Any CPU
99 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Release|x64.ActiveCfg = Release|Any CPU
100 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Release|x64.Build.0 = Release|Any CPU
101 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Release|x86.ActiveCfg = Release|Any CPU
102 | {1A27C90F-85EE-4AE6-A27B-183D0D50F62E}.Release|x86.Build.0 = Release|Any CPU
103 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
104 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Debug|Any CPU.Build.0 = Debug|Any CPU
105 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Debug|x64.ActiveCfg = Debug|Any CPU
106 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Debug|x64.Build.0 = Debug|Any CPU
107 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Debug|x86.ActiveCfg = Debug|Any CPU
108 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Debug|x86.Build.0 = Debug|Any CPU
109 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Release|Any CPU.ActiveCfg = Release|Any CPU
110 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Release|Any CPU.Build.0 = Release|Any CPU
111 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Release|x64.ActiveCfg = Release|Any CPU
112 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Release|x64.Build.0 = Release|Any CPU
113 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Release|x86.ActiveCfg = Release|Any CPU
114 | {5C57C6D6-59AB-426F-9999-FDB90864545E}.Release|x86.Build.0 = Release|Any CPU
115 | {93AF284E-BD31-456E-96AC-162C746F9479}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
116 | {93AF284E-BD31-456E-96AC-162C746F9479}.Debug|Any CPU.Build.0 = Debug|Any CPU
117 | {93AF284E-BD31-456E-96AC-162C746F9479}.Debug|x64.ActiveCfg = Debug|Any CPU
118 | {93AF284E-BD31-456E-96AC-162C746F9479}.Debug|x64.Build.0 = Debug|Any CPU
119 | {93AF284E-BD31-456E-96AC-162C746F9479}.Debug|x86.ActiveCfg = Debug|Any CPU
120 | {93AF284E-BD31-456E-96AC-162C746F9479}.Debug|x86.Build.0 = Debug|Any CPU
121 | {93AF284E-BD31-456E-96AC-162C746F9479}.Release|Any CPU.ActiveCfg = Release|Any CPU
122 | {93AF284E-BD31-456E-96AC-162C746F9479}.Release|Any CPU.Build.0 = Release|Any CPU
123 | {93AF284E-BD31-456E-96AC-162C746F9479}.Release|x64.ActiveCfg = Release|Any CPU
124 | {93AF284E-BD31-456E-96AC-162C746F9479}.Release|x64.Build.0 = Release|Any CPU
125 | {93AF284E-BD31-456E-96AC-162C746F9479}.Release|x86.ActiveCfg = Release|Any CPU
126 | {93AF284E-BD31-456E-96AC-162C746F9479}.Release|x86.Build.0 = Release|Any CPU
127 | EndGlobalSection
128 | GlobalSection(SolutionProperties) = preSolution
129 | HideSolutionNode = FALSE
130 | EndGlobalSection
131 | GlobalSection(ExtensibilityGlobals) = postSolution
132 | SolutionGuid = {9E28C5AA-F570-4825-B587-9C4710B199FD}
133 | EndGlobalSection
134 | EndGlobal
135 |
--------------------------------------------------------------------------------
/FsCodec.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | True
3 | True
4 | True
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Guidelines for this Project
2 |
3 | ## How the Walmart Security team manages security for this project
4 | Walmart takes security seriously and wants to ensure that we maintain a secure environment for our customers and that we also provide secure solutions for the open source community. To help us achieve these goals, please note the following before using this software:
5 |
6 | - Review the software license to understand Walmart's obligations in terms of warranties and suitability for purpose
7 | - Review our Responsible Disclosure Policy: https://corporate.walmart.com/article/responsible-disclosure-policy
8 | - Report any security concerns or questions using our reporting form at the bottom of our Responsible Disclosure Policy page: https://corporate.walmart.com/article/responsible-disclosure-policy
9 | - We enforce SLAs on our security team and software engineers to remediate security bugs in a timely manner
10 | - Please monitor this repository and update your environment in a timely manner as we release patches and updates
11 |
12 | ## Responsibly Disclosing Security Bugs to Walmart
13 | If you find a security bug in this repository, please work with Walmart's security team following responsible disclosure principles and these guidelines:
14 |
15 | - Do not submit a normal issue or pull request in our public repository, instead report directly on our reporting form found at the bottom of our Responsible Disclosure Policy page: https://corporate.walmart.com/article/responsible-disclosure-policy
16 | - We will review your submission and may follow up for additional details
17 | - If you have a patch, we will review it and approve it privately; once approved for release you can submit it as a pull request publicly in our repos (we give credit where credit is due)
18 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | name: $(Rev:r)
2 | jobs:
3 | - job: Windows
4 | pool:
5 | vmImage: 'windows-latest'
6 | steps:
7 | - script: dotnet test build.proj
8 | displayName: dotnet test
9 | - task: PublishTestResults@2
10 | inputs:
11 | testResultsFormat: 'VSTest'
12 | testResultsFiles: 'tests/**/*.trx'
13 | condition: succeededOrFailed()
14 | - script: dotnet pack build.proj
15 | displayName: dotnet pack build.proj
16 | env:
17 | BUILD_PR: $(SYSTEM.PULLREQUEST.PULLREQUESTNUMBER)
18 | BUILD_ID: $(BUILD.BUILDNUMBER)
19 | - task: PublishBuildArtifacts@1
20 | inputs:
21 | pathtoPublish: 'bin'
22 | artifactName: 'nupkgs'
23 | - job: Linux
24 | pool:
25 | vmImage: 'ubuntu-latest'
26 | steps:
27 | - task: UseDotNet@2
28 | inputs:
29 | useGlobalJson: true
30 | - script: dotnet test build.proj
31 | displayName: dotnet test
32 | - task: PublishTestResults@2
33 | inputs:
34 | testResultsFormat: 'VSTest'
35 | testResultsFiles: 'tests/**/*.trx'
36 | condition: succeededOrFailed()
37 | - script: dotnet pack build.proj
38 | displayName: dotnet pack
39 | - job: MacOS
40 | pool:
41 | vmImage: 'macOS-latest'
42 | steps:
43 | - task: UseDotNet@2
44 | inputs:
45 | useGlobalJson: true
46 | - script: dotnet test build.proj
47 | displayName: dotnet test
48 | - task: PublishTestResults@2
49 | inputs:
50 | testResultsFormat: 'VSTest'
51 | testResultsFiles: 'tests/**/*.trx'
52 | condition: succeededOrFailed()
53 | - script: dotnet pack build.proj
54 | displayName: dotnet pack
55 |
--------------------------------------------------------------------------------
/build.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | --configuration Release
7 |
8 | /p:BUILD_PR=$(BUILD_PR)
9 | /p:BUILD_ID=$(BUILD_ID) $(PrOption) -o $(MSBuildThisFileDirectory)bin
10 |
11 | --logger:trx
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "9.0.100",
4 | "rollForward": "latestMajor"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/FsCodec.Box/ByteArray.fs:
--------------------------------------------------------------------------------
1 | namespace FsCodec
2 |
3 | open System
4 | open System.Runtime.CompilerServices
5 |
6 | []
7 | type ByteArray private () =
8 |
9 | static member BytesToReadOnlyMemory(x: byte[]): ReadOnlyMemory =
10 | if x = null then ReadOnlyMemory.Empty
11 | else ReadOnlyMemory x
12 |
13 | static member ReadOnlyMemoryToBytes(x: ReadOnlyMemory): byte[] =
14 | if x.IsEmpty then null
15 | else x.ToArray()
16 |
17 | /// Adapt an IEventCodec that handles ReadOnlyMemory<byte> Event Bodies to instead use byte[]
18 | /// Ideally not used as it makes pooling problematic; only provided for interop/porting scaffolding wrt Equinox V3 and EventStore.Client etc
19 | []
20 | static member AsByteArray<'Event, 'Context>(native: IEventCodec<'Event, ReadOnlyMemory, 'Context>)
21 | : IEventCodec<'Event, byte[], 'Context> =
22 | FsCodec.Core.EventCodec.mapBodies ByteArray.ReadOnlyMemoryToBytes ByteArray.BytesToReadOnlyMemory native
23 |
24 | []
25 | static member ToByteArrayCodec<'Event, 'Context>(native: IEventCodec<'Event, ReadOnlyMemory, 'Context>)
26 | : IEventCodec<'Event, byte[], 'Context> =
27 | FsCodec.Core.EventCodec.mapBodies ByteArray.ReadOnlyMemoryToBytes ByteArray.BytesToReadOnlyMemory native
28 |
--------------------------------------------------------------------------------
/src/FsCodec.Box/Codec.fs:
--------------------------------------------------------------------------------
1 | // Mirror of FsCodec.NewtonsoftJson/SystemTextJson.Codec intended to provide equivalent calls and functionality, without actually serializing/deserializing as JSON
2 | // This is a useful facility for in-memory stores such as Equinox's MemoryStore as it enables you to
3 | // - efficiently test behaviors from an event sourced decision processing perspective (e.g. with Property Based Tests)
4 | // - without paying a serialization cost and/or having to deal with sanitization of generated data in order to make it roundtrippable through same
5 | namespace FsCodec.Box
6 |
7 | open System
8 | open System.Runtime.InteropServices
9 |
10 | /// Provides Codecs that render to boxed object, ideal for usage in a Memory Store.
11 | /// Requires that Contract types adhere to the conventions implied by using TypeShape.UnionContract.UnionContractEncoder
12 | /// If you need full control and/or have have your own codecs, see FsCodec.Codec.Create instead.
13 | /// See for example usage.
14 | []
15 | type Codec private () =
16 |
17 | static let defEncoder: TypeShape.UnionContract.IEncoder = TypeShape.UnionContract.BoxEncoder() :> _
18 |
19 | /// Generate an IEventCodec that handles obj (boxed .NET Object) Event Bodies.
20 | /// Uses up, down functions to handle upconversion/downconversion and eventId/correlationId/causationId mapping
21 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
22 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name;
23 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
24 | static member Create<'Event, 'Contract, 'Meta, 'Context when 'Contract :> TypeShape.UnionContract.IUnionContract>
25 | ( // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
26 | // to the 'Event representation (typically a Discriminated Union) that is to be presented to the programming model.
27 | up: Func, 'Contract, 'Event>,
28 | // Maps a fresh Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
29 | // The function is also expected to derive an optional meta object that will be serialized with the same encoder,
30 | // and eventId, correlationId, causationId and an Event Creationtimestamp.
31 | down: Func<'Context, 'Event, struct ('Contract * 'Meta voption * Guid * string * string * DateTimeOffset)>,
32 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
33 | [] ?rejectNullaryCases)
34 | : FsCodec.IEventCodec<'Event, obj, 'Context> =
35 | FsCodec.Core.Codec.Create(defEncoder, up, down, ?rejectNullaryCases = rejectNullaryCases)
36 |
37 | /// Generate an IEventCodec that handles obj (boxed .NET Object) Event Bodies.
38 | /// Uses up, down and mapCausation functions to facilitate upconversion/downconversion and eventId/correlationId/causationId/timestamp mapping
39 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
40 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name;
41 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
42 | static member Create<'Event, 'Contract, 'Meta, 'Context when 'Contract :> TypeShape.UnionContract.IUnionContract>
43 | ( // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
44 | // to the representation (typically a Discriminated Union) that is to be presented to the programming model.
45 | up: Func, 'Contract, 'Event>,
46 | // Maps a fresh Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
47 | // The function is also expected to derive
48 | // a meta object that will be serialized with the same options (if it's not None)
49 | // and an Event Creation timestamp (Default: DateTimeOffset.UtcNow).
50 | down: Func<'Event, struct ('Contract * 'Meta voption * DateTimeOffset voption)>,
51 | // Uses the 'Context passed to the Encode call and the 'Meta emitted by down to a) the final metadata b) the eventId c) the correlationId and d) the causationId
52 | mapCausation: Func<'Context, 'Meta voption, struct ('Meta voption * Guid * string * string)>,
53 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
54 | [] ?rejectNullaryCases)
55 | : FsCodec.IEventCodec<'Event, obj, 'Context> =
56 | FsCodec.Core.Codec.Create(defEncoder, up, down, mapCausation, ?rejectNullaryCases = rejectNullaryCases)
57 |
58 | /// Generate an IEventCodec that handles obj (boxed .NET Object) Event Bodies.
59 | /// Uses up and down functions to facilitate upconversion/downconversion/timestamping without eventId/correlation/causationId mapping
60 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
61 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name
62 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
63 | static member Create<'Event, 'Contract, 'Meta when 'Contract :> TypeShape.UnionContract.IUnionContract>
64 | ( // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
65 | // to the representation (typically a Discriminated Union) that is to be presented to the programming model.
66 | up: Func, 'Contract, 'Event>,
67 | // Maps a fresh 'Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
68 | // The function is also expected to derive
69 | // a meta object that will be serialized with the same options (if it's not None)
70 | // and an Event Creation timestamp (Default: DateTimeOffset.UtcNow).
71 | down: Func<'Event, struct ('Contract * 'Meta voption * DateTimeOffset voption)>,
72 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
73 | [] ?rejectNullaryCases)
74 | : FsCodec.IEventCodec<'Event, obj, unit> =
75 | FsCodec.Core.Codec.Create(defEncoder, up, down, ?rejectNullaryCases = rejectNullaryCases)
76 |
77 | /// Generate an IEventCodec that handles obj (boxed .NET Object) Event Bodies.
78 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name
79 | /// 'Union must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
80 | static member Create<'Union when 'Union :> TypeShape.UnionContract.IUnionContract>
81 | ( // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
82 | [] ?rejectNullaryCases)
83 | : FsCodec.IEventCodec<'Union, obj, unit> =
84 | FsCodec.Core.Codec.Create(defEncoder, ?rejectNullaryCases = rejectNullaryCases)
85 |
--------------------------------------------------------------------------------
/src/FsCodec.Box/Compression.fs:
--------------------------------------------------------------------------------
1 | namespace FsCodec
2 |
3 | open System
4 | open System.Runtime.CompilerServices
5 | open System.Runtime.InteropServices
6 |
7 | type [] CompressionOptions = { minSize: int; minGain: int } with
8 | static member Default = { minSize = 48; minGain = 4 }
9 | static member Uncompressed = { minSize = Int32.MaxValue; minGain = 0 }
10 |
11 | []
12 | type Compression private () =
13 |
14 | static member Utf8ToEncodedDirect(x: ReadOnlyMemory): Encoded =
15 | FsCodec.Encoding.OfBlob x
16 | static member Utf8ToEncodedTryCompress(options, x: ReadOnlyMemory): Encoded =
17 | FsCodec.Encoding.OfBlobCompress({ minSize = options.minSize; minGain = options.minGain }, x)
18 | static member EncodedToUtf8(x: Encoded): ReadOnlyMemory =
19 | FsCodec.Encoding.ToBlob x
20 | /// NOTE if this is for use with System.Text.Encoding.UTF8.GetString, then EncodedToUtf8 >> _.Span is more efficient
21 | static member EncodedToByteArray(x: Encoded): byte[] =
22 | FsCodec.Encoding.ToBlob(x).ToArray()
23 |
24 | /// Adapts an IEventCodec rendering to ReadOnlyMemory<byte> Event Bodies to attempt to compress the data.
25 | /// If sufficient compression, as defined by options is not achieved, the body is saved as-is.
26 | /// The int conveys a value that must be round tripped alongside the body in order for the decoding process to correctly interpret it.
27 | []
28 | static member EncodeTryCompress<'Event, 'Context>(native: IEventCodec<'Event, ReadOnlyMemory, 'Context>, [] ?options)
29 | : IEventCodec<'Event, Encoded, 'Context> =
30 | let opts = defaultArg options CompressionOptions.Default
31 | let opts: FsCodec.CompressionOptions = { minSize = opts.minSize; minGain = opts.minGain }
32 | FsCodec.Core.EventCodec.mapBodies (fun d -> Encoding.OfBlobCompress(opts, d)) Encoding.ToBlob native
33 |
34 | /// Adapts an IEventCodec rendering to ReadOnlyMemory<byte> Event Bodies to encode as per EncodeTryCompress, but without attempting compression.
35 | []
36 | static member EncodeUncompressed<'Event, 'Context>(native: IEventCodec<'Event, ReadOnlyMemory, 'Context>)
37 | : IEventCodec<'Event, Encoded, 'Context> =
38 | Encoder.Uncompressed native
39 |
40 | /// Adapts an IEventCodec rendering to int * ReadOnlyMemory<byte> Event Bodies to render and/or consume from Uncompressed ReadOnlyMemory<byte>.
41 | []
42 | static member ToUtf8Codec<'Event, 'Context>(native: IEventCodec<'Event, Encoded, 'Context>)
43 | : IEventCodec<'Event, ReadOnlyMemory, 'Context> =
44 | Encoder.AsBlob native
45 |
46 | /// Adapts an IEventCodec rendering to int * ReadOnlyMemory<byte> Event Bodies to render and/or consume from Uncompressed byte[].
47 | []
48 | static member ToByteArrayCodec<'Event, 'Context>(native: IEventCodec<'Event, Encoded, 'Context>)
49 | : IEventCodec<'Event, byte[], 'Context> =
50 | Encoder.AsByteArray native
51 |
--------------------------------------------------------------------------------
/src/FsCodec.Box/CoreCodec.fs:
--------------------------------------------------------------------------------
1 | namespace FsCodec.Core
2 |
3 | open System
4 | open System.Runtime.InteropServices
5 |
6 | /// Low-level Codec Generator that encodes to a Generic Event 'Body Type.
7 | /// Requires that Contract types adhere to the conventions implied by using TypeShape.UnionContract.UnionContractEncoder
8 | /// If you need full control and/or have have your own codecs, see FsCodec.Codec.Create instead.
9 | /// See non-Core namespace for application level encoders.
10 | []
11 | type Codec private () =
12 |
13 | /// Generate an IEventCodec using the supplied encoder.
14 | /// Uses up, down functions to handle upconversion/downconversion and eventId/correlationId/causationId mapping
15 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
16 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name;
17 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
18 | static member Create<'Event, 'Contract, 'Meta, 'Body, 'Context when 'Contract :> TypeShape.UnionContract.IUnionContract>
19 | ( encoder,
20 | // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
21 | // to the 'Event representation (typically a Discriminated Union) that is to be presented to the programming model.
22 | up: Func, 'Contract, 'Event>,
23 | // Maps a fresh Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
24 | // The function is also expected to derive an optional meta object that will be serialized with the same encoder,
25 | // and eventId, correlationId, causationId and an Event Creationtimestamp.
26 | down: Func<'Context, 'Event, struct ('Contract * 'Meta voption * Guid * string * string * DateTimeOffset)>,
27 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
28 | [] ?rejectNullaryCases)
29 | : FsCodec.IEventCodec<'Event, 'Body, 'Context> =
30 |
31 | let dataCodec =
32 | TypeShape.UnionContract.UnionContractEncoder.Create<'Contract, 'Body>(
33 | encoder,
34 | // Round-tripping cases like null and/or empty strings etc involves edge cases that stores,
35 | // FsCodec.NewtonsoftJson.Codec, Interop.fs and InteropTests.fs do not cover, so we disable this
36 | requireRecordFields = true,
37 | allowNullaryCases = not (defaultArg rejectNullaryCases false))
38 |
39 | { new FsCodec.IEventCodec<'Event, 'Body, 'Context> with
40 |
41 | member _.Encode(context, event) =
42 | let struct (c, meta: 'Meta voption, eventId, correlationId, causationId, timestamp) = down.Invoke(context, event)
43 | let enc = dataCodec.Encode c
44 | let meta' = match meta with ValueSome x -> encoder.Encode<'Meta> x | ValueNone -> Unchecked.defaultof<'Body>
45 | EventData(enc.CaseName, enc.Payload, meta', eventId, correlationId, causationId, timestamp)
46 |
47 | member _.Decode encoded =
48 | match dataCodec.TryDecode { CaseName = encoded.EventType; Payload = encoded.Data } with
49 | | None -> ValueNone
50 | | Some contract -> up.Invoke(encoded, contract) |> ValueSome }
51 |
52 | /// Generate an IEventCodec using the supplied encoder.
53 | /// Uses up, down and mapCausation functions to facilitate upconversion/downconversion and eventId/correlationId/causationId/timestamp mapping
54 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
55 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name;
56 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
57 | static member Create<'Event, 'Contract, 'Meta, 'Body, 'Context when 'Contract :> TypeShape.UnionContract.IUnionContract>
58 | ( encoder,
59 | // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
60 | // to the representation (typically a Discriminated Union) that is to be presented to the programming model.
61 | up: Func, 'Contract, 'Event>,
62 | // Maps a fresh Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
63 | // The function is also expected to derive
64 | // a meta object that will be serialized with the same options (if it's not None)
65 | // and an Event Creation timestamp (Default: DateTimeOffset.UtcNow).
66 | down: Func<'Event, struct ('Contract * 'Meta voption * DateTimeOffset voption)>,
67 | // Uses the 'Context passed to the Encode call and the 'Meta emitted by down to produce a) the final metadata b) the eventId c) the correlationId and d) the causationId
68 | mapCausation: Func<'Context, 'Meta voption, struct ('Meta voption * Guid * string * string)>,
69 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
70 | [] ?rejectNullaryCases)
71 | : FsCodec.IEventCodec<'Event, 'Body, 'Context> =
72 |
73 | let down context union =
74 | let struct (c, m, t) = down.Invoke union
75 | let struct (m', eventId, correlationId, causationId) = mapCausation.Invoke(context, m)
76 | struct (c, m', eventId, correlationId, causationId, match t with ValueSome t -> t | ValueNone -> DateTimeOffset.UtcNow)
77 | Codec.Create(encoder, up = up, down = down, ?rejectNullaryCases = rejectNullaryCases)
78 |
79 | /// Generate an IEventCodec using the supplied encoder.
80 | /// Uses up and down functions to facilitate upconversion/downconversion/timestamping without eventId/correlation/causationId mapping
81 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
82 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name
83 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
84 | static member Create<'Event, 'Contract, 'Meta, 'Body when 'Contract :> TypeShape.UnionContract.IUnionContract>
85 | ( encoder,
86 | // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
87 | // to the representation (typically a Discriminated Union) that is to be presented to the programming model.
88 | up: Func, 'Contract, 'Event>,
89 | // Maps a fresh 'Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
90 | // The function is also expected to derive
91 | // a meta object that will be serialized with the same options (if it's not None)
92 | // and an Event Creation timestamp (Default: DateTimeOffset.UtcNow).
93 | down: Func<'Event, struct ('Contract * 'Meta voption * DateTimeOffset voption)>,
94 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
95 | [] ?rejectNullaryCases)
96 | : FsCodec.IEventCodec<'Event, 'Body, unit> =
97 |
98 | let mapCausation () (m: 'Meta voption) = struct (m, Guid.NewGuid(), null, null)
99 | Codec.Create(encoder, up = up, down = down, mapCausation = mapCausation, ?rejectNullaryCases = rejectNullaryCases)
100 |
101 | /// Generate an IEventCodec using the supplied encoder.
102 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name
103 | /// 'Union must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
104 | static member Create<'Body, 'Union when 'Union :> TypeShape.UnionContract.IUnionContract>
105 | ( encoder: TypeShape.UnionContract.IEncoder<'Body>,
106 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
107 | [] ?rejectNullaryCases)
108 | : FsCodec.IEventCodec<'Union, 'Body, unit> =
109 |
110 | let up (_e: FsCodec.ITimelineEvent<'Body>) (u: 'Union): 'Union = u
111 | let down (event: 'Union) = struct (event, ValueNone (*Meta*), ValueNone (*Timestamp*))
112 | Codec.Create(encoder, up = up, down = down, ?rejectNullaryCases = rejectNullaryCases)
113 |
--------------------------------------------------------------------------------
/src/FsCodec.Box/FsCodec.Box.fsproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | netstandard2.1
7 | 3.0.0
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/FsCodec.NewtonsoftJson/Codec.fs:
--------------------------------------------------------------------------------
1 | namespace FsCodec.NewtonsoftJson.Core
2 |
3 | /// Newtonsoft.Json implementation of TypeShape.UnionContractEncoder's IEncoder that encodes direct to a UTF-8 ReadOnlyMemory
4 | type ReadOnlyMemoryEncoder(serdes: FsCodec.NewtonsoftJson.Serdes) =
5 | interface TypeShape.UnionContract.IEncoder> with
6 | member _.Empty = System.ReadOnlyMemory.Empty
7 | member _.Encode(value: 'T) = serdes.SerializeToUtf8(value) |> System.ReadOnlyMemory
8 | member _.Decode(utf8json: System.ReadOnlyMemory): 'T = serdes.Deserialize<'T>(utf8json)
9 |
10 | namespace FsCodec.NewtonsoftJson
11 |
12 | open Newtonsoft.Json
13 | open System
14 | open System.Runtime.InteropServices
15 |
16 | /// Provides Codecs that render to a ReadOnlyMemory<byte>, suitable for storage in Event Stores that handle Event Data and Metadata as opaque blobs.
17 | /// Requires that Contract types adhere to the conventions implied by using TypeShape.UnionContract.UnionContractEncoder
18 | /// If you need full control and/or have have your own codecs, see FsCodec.Codec.Create instead.
19 | /// See for example usage.
20 | []
21 | type Codec private () =
22 |
23 | static let defEncoder: Lazy>> = lazy (Core.ReadOnlyMemoryEncoder Serdes.Default :> _)
24 | static let mkEncoder: Serdes option * JsonSerializerSettings option -> TypeShape.UnionContract.IEncoder> = function
25 | | None, None -> defEncoder.Value
26 | | Some serdes, None -> Core.ReadOnlyMemoryEncoder(serdes)
27 | | _, Some opts -> Core.ReadOnlyMemoryEncoder(Serdes opts)
28 |
29 | /// Generate an IEventCodec that handles ReadOnlyMemory<byte> Event Bodies using the supplied Newtonsoft.Json.JsonSerializerSettings options.
30 | /// Uses up, down functions to handle upconversion/downconversion and eventId/correlationId/causationId mapping
31 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
32 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name;
33 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
34 | static member Create<'Event, 'Contract, 'Meta, 'Context when 'Contract :> TypeShape.UnionContract.IUnionContract>
35 | ( // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
36 | // to the 'Event representation (typically a Discriminated Union) that is to be presented to the programming model.
37 | up: Func>, 'Contract, 'Event>,
38 | // Maps a fresh Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
39 | // The function is also expected to derive an optional meta object that will be serialized with the same encoder,
40 | // and eventId, correlationId, causationId and an Event Creationtimestamp.
41 | down: Func<'Context, 'Event, struct ('Contract * 'Meta voption * Guid * string * string * DateTimeOffset)>,
42 | // Configuration to be used by the underlying Newtonsoft.Json Serializer when encoding/decoding. Defaults to same as Options.Default
43 | [] ?options, [] ?serdes,
44 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
45 | [] ?rejectNullaryCases)
46 | : FsCodec.IEventCodec<'Event, ReadOnlyMemory, 'Context> =
47 | FsCodec.Core.Codec.Create(mkEncoder (serdes, options), up, down, ?rejectNullaryCases = rejectNullaryCases)
48 |
49 | /// Generate an IEventCodec that handles ReadOnlyMemory<byte> Event Bodies using the supplied Newtonsoft.Json.JsonSerializerSettings options.
50 | /// Uses up, down and mapCausation functions to facilitate upconversion/downconversion and eventId/correlationId/causationId/timestamp mapping
51 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
52 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name;
53 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
54 | static member Create<'Event, 'Contract, 'Meta, 'Context when 'Contract :> TypeShape.UnionContract.IUnionContract>
55 | ( // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
56 | // to the representation (typically a Discriminated Union) that is to be presented to the programming model.
57 | up: Func>, 'Contract, 'Event>,
58 | // Maps a fresh Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
59 | // The function is also expected to derive
60 | // a meta object that will be serialized with the same options (if it's not None)
61 | // and an Event Creation timestamp (Default: DateTimeOffset.UtcNow).
62 | down: Func<'Event, struct ('Contract * 'Meta voption * DateTimeOffset voption)>,
63 | // Uses the 'Context passed to the Encode call and the 'Meta emitted by down to a) the final metadata b) the eventId c) the correlationId and d) the causationId
64 | mapCausation: Func<'Context, 'Meta voption, struct ('Meta voption * Guid * string * string)>,
65 | // Configuration to be used by the underlying Newtonsoft.Json Serializer when encoding/decoding. Defaults to same as Options.Default
66 | [] ?options, [] ?serdes,
67 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
68 | [] ?rejectNullaryCases)
69 | : FsCodec.IEventCodec<'Event, ReadOnlyMemory, 'Context> =
70 | FsCodec.Core.Codec.Create(mkEncoder (serdes, options), up, down, mapCausation, ?rejectNullaryCases = rejectNullaryCases)
71 |
72 | /// Generate an IEventCodec that handles ReadOnlyMemory<byte> Event Bodies using the supplied Newtonsoft.Json.JsonSerializerSettings options.
73 | /// Uses up and down functions to facilitate upconversion/downconversion/timestamping without eventId/correlation/causationId mapping
74 | /// and/or surfacing metadata to the programming model by including it in the emitted 'Event
75 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name
76 | /// Contract must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
77 | static member Create<'Event, 'Contract, 'Meta when 'Contract :> TypeShape.UnionContract.IUnionContract>
78 | ( // Maps from the TypeShape UnionConverter 'Contract case the Event has been mapped to (with the raw event data as context)
79 | // to the representation (typically a Discriminated Union) that is to be presented to the programming model.
80 | up: Func>, 'Contract, 'Event>,
81 | // Maps a fresh 'Event resulting from a Decision in the Domain representation type down to the TypeShape UnionConverter 'Contract
82 | // The function is also expected to derive
83 | // a meta object that will be serialized with the same options (if it's not None)
84 | // and an Event Creation timestamp.
85 | down: Func<'Event, struct ('Contract * 'Meta voption * DateTimeOffset voption)>,
86 | // Configuration to be used by the underlying Newtonsoft.Json Serializer when encoding/decoding. Defaults to same as Options.Default
87 | [] ?options, [] ?serdes,
88 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
89 | [] ?rejectNullaryCases)
90 | : FsCodec.IEventCodec<'Event, ReadOnlyMemory, unit> =
91 | FsCodec.Core.Codec.Create(mkEncoder (serdes, options), up, down, ?rejectNullaryCases = rejectNullaryCases)
92 |
93 | /// Generate an IEventCodec that handles ReadOnlyMemory<byte> Event Bodies using the supplied Newtonsoft.Json.JsonSerializerSettings options.
94 | /// The Event Type Names are inferred based on either explicit DataMember(Name= Attributes, or (if unspecified) the Discriminated Union Case Name
95 | /// 'Union must be tagged with interface TypeShape.UnionContract.IUnionContract to signify this scheme applies.
96 | static member Create<'Union when 'Union :> TypeShape.UnionContract.IUnionContract>
97 | ( // Configuration to be used by the underlying Newtonsoft.Json Serializer when encoding/decoding. Defaults to same as Options.Default
98 | [] ?options, [] ?serdes,
99 | // Enables one to fail encoder generation if union contains nullary cases. Defaults to false, i.e. permitting them.
100 | [] ?rejectNullaryCases)
101 | : FsCodec.IEventCodec<'Union, ReadOnlyMemory, unit> =
102 | FsCodec.Core.Codec.Create(mkEncoder (serdes, options), ?rejectNullaryCases = rejectNullaryCases)
103 |
--------------------------------------------------------------------------------
/src/FsCodec.NewtonsoftJson/FsCodec.NewtonsoftJson.fsproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | netstandard2.1
6 | 3.0.0
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/FsCodec.NewtonsoftJson/OptionConverter.fs:
--------------------------------------------------------------------------------
1 | namespace FsCodec.NewtonsoftJson
2 |
3 | open Newtonsoft.Json
4 | open System
5 |
6 | /// For Some 1 generates "1", for None generates "null"
7 | type OptionConverter() =
8 | inherit JsonConverter()
9 |
10 | override _.CanConvert(t: Type) = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof