Skip to content

Commit f018f62

Browse files
authored
feat(TypeSafeEnum): Add caseValues (#115)
1 parent ca01ebb commit f018f62

File tree

5 files changed

+22
-2
lines changed

5 files changed

+22
-2
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ The `Unreleased` section name is replaced by the expected version of next releas
99
## [Unreleased]
1010

1111
### Added
12+
13+
### Added
14+
15+
- `TypeSafeEnum.caseValues<'t>`: Yields all values of a union (that is a `TypeSafeEnum`) [#115](https://github.com/jet/FsCodec/pull/115)
16+
1217
### Changed
1318
### Removed
1419
### Fixed

src/FsCodec/TypeSafeEnum.fs

+3
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@ let parseF<'T> f =
3030
let parse<'T> = parseF<'T> (=)
3131

3232
let toString<'t> : 't -> string = Union.caseName<'t>
33+
34+
/// <summary>Yields all the cases available for <c>'t</c>, which must be a <c>TypeSafeEnum</c>, i.e. have only nullary cases.</summary>
35+
let caseValues<'t> : 't[] = Union.Info.caseValues<'t>

src/FsCodec/Union.fs

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ module Info =
2626
let getCase value = cases[getTag value]
2727
{ cases = cases; getCase = getCase })
2828
let tryFindCaseWithName u (predicate: string -> bool): CaseInfo option = u.cases |> Array.tryFind (fun c -> predicate c.name)
29-
let private caseValues: Type -> obj[] = memoize (fun t -> (get t).cases |> Array.map (fun c -> c.construct Array.empty))
29+
let caseValues<'t> : 't[] = (get typeof<'t>).cases |> Array.map (fun c -> c.construct Array.empty :?> 't)
30+
let caseValuesT: Type -> obj[] = memoize (fun t -> (get t).cases |> Array.map (fun c -> c.construct Array.empty))
3031
let tryFindCaseValueWithName (t: Type): (string -> bool) -> obj option =
3132
let u = get t
32-
let caseValue = let values = caseValues t in fun i -> values[i]
33+
let caseValue = let values = caseValuesT t in fun i -> values[i]
3334
fun predicate -> u.cases |> Array.tryFindIndex (fun c -> predicate c.name) |> Option.map caseValue
3435

3536
/// Determines whether the type is a Union

tests/FsCodec.Tests/FsCodec.Tests.fsproj

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<ItemGroup>
99
<Compile Include="StreamNameTests.fs" />
1010
<Compile Include="CompressionTests.fs" />
11+
<Compile Include="TypeSafeEnumTests.fs" />
1112
</ItemGroup>
1213

1314
<ItemGroup>
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module FsCodec.Tests.TypeSafeEnumTests
2+
3+
open FsCodec
4+
open Swensen.Unquote
5+
open Xunit
6+
7+
type Outcome = Joy | Pain | Misery
8+
9+
let [<Fact>] caseNames () =
10+
[| Joy; Pain; Misery |] =! TypeSafeEnum.caseValues<_>

0 commit comments

Comments
 (0)