Added boundedEnumCodec

This commit is contained in:
Pablo Bollansée 2024-09-01 12:39:58 +01:00 committed by Tom Sydney Kerckhove
parent f19887d136
commit be4aba9ef1
32 changed files with 318 additions and 62 deletions

View File

@ -78,6 +78,7 @@ extra-source-files:
test_resources/json-schema/semigroup-first.json test_resources/json-schema/semigroup-first.json
test_resources/json-schema/semigroup-last.json test_resources/json-schema/semigroup-last.json
test_resources/json-schema/set-text.json test_resources/json-schema/set-text.json
test_resources/json-schema/shape.json
test_resources/json-schema/string.json test_resources/json-schema/string.json
test_resources/json-schema/text.json test_resources/json-schema/text.json
test_resources/json-schema/these.json test_resources/json-schema/these.json
@ -144,6 +145,7 @@ extra-source-files:
test_resources/nix/semigroup-first-type.nix test_resources/nix/semigroup-first-type.nix
test_resources/nix/semigroup-last-type.nix test_resources/nix/semigroup-last-type.nix
test_resources/nix/set-text-type.nix test_resources/nix/set-text-type.nix
test_resources/nix/shape-type.nix
test_resources/nix/string-type.nix test_resources/nix/string-type.nix
test_resources/nix/text-type.nix test_resources/nix/text-type.nix
test_resources/nix/these-options.nix test_resources/nix/these-options.nix
@ -183,6 +185,7 @@ extra-source-files:
test_resources/openapi-schema/declareSchemaRef/recursive.json test_resources/openapi-schema/declareSchemaRef/recursive.json
test_resources/openapi-schema/declareSchemaRef/semigroup-first.json test_resources/openapi-schema/declareSchemaRef/semigroup-first.json
test_resources/openapi-schema/declareSchemaRef/semigroup-last.json test_resources/openapi-schema/declareSchemaRef/semigroup-last.json
test_resources/openapi-schema/declareSchemaRef/shape.json
test_resources/openapi-schema/declareSchemaRef/these.json test_resources/openapi-schema/declareSchemaRef/these.json
test_resources/openapi-schema/declareSchemaRef/very-comment.json test_resources/openapi-schema/declareSchemaRef/very-comment.json
test_resources/openapi-schema/declareSchemaRef/via.json test_resources/openapi-schema/declareSchemaRef/via.json
@ -227,6 +230,7 @@ extra-source-files:
test_resources/openapi-schema/semigroup-first.json test_resources/openapi-schema/semigroup-first.json
test_resources/openapi-schema/semigroup-last.json test_resources/openapi-schema/semigroup-last.json
test_resources/openapi-schema/set-text.json test_resources/openapi-schema/set-text.json
test_resources/openapi-schema/shape.json
test_resources/openapi-schema/string.json test_resources/openapi-schema/string.json
test_resources/openapi-schema/text.json test_resources/openapi-schema/text.json
test_resources/openapi-schema/these.json test_resources/openapi-schema/these.json
@ -285,6 +289,7 @@ extra-source-files:
test_resources/show-codec/semigroup-first.txt test_resources/show-codec/semigroup-first.txt
test_resources/show-codec/semigroup-last.txt test_resources/show-codec/semigroup-last.txt
test_resources/show-codec/set-text.txt test_resources/show-codec/set-text.txt
test_resources/show-codec/shape.txt
test_resources/show-codec/string.txt test_resources/show-codec/string.txt
test_resources/show-codec/text.txt test_resources/show-codec/text.txt
test_resources/show-codec/these.txt test_resources/show-codec/these.txt
@ -346,6 +351,7 @@ extra-source-files:
test_resources/swagger-schema/semigroup-first.json test_resources/swagger-schema/semigroup-first.json
test_resources/swagger-schema/semigroup-last.json test_resources/swagger-schema/semigroup-last.json
test_resources/swagger-schema/set-text.json test_resources/swagger-schema/set-text.json
test_resources/swagger-schema/shape.json
test_resources/swagger-schema/string.json test_resources/swagger-schema/string.json
test_resources/swagger-schema/text.json test_resources/swagger-schema/text.json
test_resources/swagger-schema/these.json test_resources/swagger-schema/these.json
@ -399,6 +405,7 @@ extra-source-files:
test_resources/yaml-schema/recursive.txt test_resources/yaml-schema/recursive.txt
test_resources/yaml-schema/scientific.txt test_resources/yaml-schema/scientific.txt
test_resources/yaml-schema/set-text.txt test_resources/yaml-schema/set-text.txt
test_resources/yaml-schema/shape.txt
test_resources/yaml-schema/string.txt test_resources/yaml-schema/string.txt
test_resources/yaml-schema/text.txt test_resources/yaml-schema/text.txt
test_resources/yaml-schema/these.txt test_resources/yaml-schema/these.txt

View File

@ -74,6 +74,7 @@ main =
comparisonBench @DiffTime, comparisonBench @DiffTime,
comparisonBench @NominalDiffTime, comparisonBench @NominalDiffTime,
comparisonBench @Fruit, comparisonBench @Fruit,
comparisonBench @Shape,
comparisonBench @Example, comparisonBench @Example,
comparisonBench @Recursive, comparisonBench @Recursive,
comparisonBench @Via, comparisonBench @Via,

View File

@ -94,6 +94,28 @@ instance FromJSON Fruit
instance ToJSON Fruit instance ToJSON Fruit
data Shape
= ShapeCircle
| ShapeSquare
| ShapeRectangle
deriving (Show, Eq, Generic, Enum, Bounded)
deriving (FromJSON, ToJSON) via Autodocodec Shape
deriving (OpenAPI.ToSchema) via AutodocodecOpenApi Shape
instance Validity Shape
instance NFData Shape
instance GenValid Shape where
genValid = genValidStructurallyWithoutExtraChecking
shrinkValid = shrinkValidStructurallyWithoutExtraFiltering
instance HasCodec Shape where
codec = boundedEnumCodec $ \case
ShapeCircle -> "circle"
ShapeSquare -> "square"
ShapeRectangle -> "rectangle"
-- | A complex example type -- | A complex example type
data Example = Example data Example = Example
{ exampleText :: !Text, { exampleText :: !Text,
@ -104,7 +126,8 @@ data Example = Example
exampleOptionalWithDefault :: !Text, exampleOptionalWithDefault :: !Text,
exampleOptionalWithNullDefault :: ![Text], exampleOptionalWithNullDefault :: ![Text],
exampleSingleOrList :: ![Text], exampleSingleOrList :: ![Text],
exampleFruit :: !Fruit exampleFruit :: !Fruit,
exampleShape :: !Shape
} }
deriving (Show, Eq, Generic) deriving (Show, Eq, Generic)
deriving (OpenAPI.ToSchema) via (AutodocodecOpenApi Example) deriving (OpenAPI.ToSchema) via (AutodocodecOpenApi Example)
@ -132,6 +155,7 @@ instance HasObjectCodec Example where
<*> optionalFieldWithOmittedDefault "optional-with-null-default" [] "an optional list of texts with a default empty list where the empty list would be omitted" .= exampleOptionalWithNullDefault <*> optionalFieldWithOmittedDefault "optional-with-null-default" [] "an optional list of texts with a default empty list where the empty list would be omitted" .= exampleOptionalWithNullDefault
<*> optionalFieldWithOmittedDefaultWith "single-or-list" (singleOrListCodec codec) [] "an optional list that can also be specified as a single element" .= exampleSingleOrList <*> optionalFieldWithOmittedDefaultWith "single-or-list" (singleOrListCodec codec) [] "an optional list that can also be specified as a single element" .= exampleSingleOrList
<*> requiredField "fruit" "fruit!!" .= exampleFruit <*> requiredField "fruit" "fruit!!" .= exampleFruit
<*> requiredField "shape" "shape!?" .= exampleShape
instance ToJSON Example where instance ToJSON Example where
toJSON Example {..} = toJSON Example {..} =
@ -141,6 +165,7 @@ instance ToJSON Example where
"bool" JSON..= exampleBool, "bool" JSON..= exampleBool,
"maybe" JSON..= exampleRequiredMaybe, "maybe" JSON..= exampleRequiredMaybe,
"fruit" JSON..= exampleFruit, "fruit" JSON..= exampleFruit,
"shape" JSON..= exampleShape,
"optional-with-default" JSON..= exampleOptionalWithDefault "optional-with-default" JSON..= exampleOptionalWithDefault
], ],
[ "optional" JSON..= opt [ "optional" JSON..= opt
@ -173,6 +198,7 @@ instance FromJSON Example where
<|> (o JSON..:? "single-or-list" JSON..!= []) <|> (o JSON..:? "single-or-list" JSON..!= [])
) )
<*> o JSON..: "fruit" <*> o JSON..: "fruit"
<*> o JSON..: "shape"
instance FromMultipart tag Example where instance FromMultipart tag Example where
fromMultipart form = fromMultipart form =
@ -203,6 +229,12 @@ instance FromMultipart tag Example where
"Melon" -> Right Melon "Melon" -> Right Melon
_ -> Left "unknown fruit" _ -> Left "unknown fruit"
) )
<*> ( lookupInput "shape" form >>= \case
"circle" -> Right ShapeCircle
"square" -> Right ShapeSquare
"rectangle" -> Right ShapeRectangle
_ -> Left "unknown shape"
)
instance ToMultipart tag Example where instance ToMultipart tag Example where
toMultipart Example {..} = toMultipart Example {..} =
@ -217,7 +249,12 @@ instance ToMultipart tag Example where
[Input "optional-with-default" exampleOptionalWithDefault], [Input "optional-with-default" exampleOptionalWithDefault],
map (Input "optional-with-null-default") exampleOptionalWithNullDefault, map (Input "optional-with-null-default") exampleOptionalWithNullDefault,
map (Input "single-or-list") exampleSingleOrList, map (Input "single-or-list") exampleSingleOrList,
[Input "fruit" $ T.pack $ show exampleFruit] [Input "fruit" $ T.pack $ show exampleFruit],
[ Input "shape" $ case exampleShape of
ShapeCircle -> "circle"
ShapeSquare -> "square"
ShapeRectangle -> "rectangle"
]
] ]
) )
[] []

View File

@ -85,6 +85,7 @@ spec = do
jsonSchemaSpec @NominalDiffTime "nominal-difftime" jsonSchemaSpec @NominalDiffTime "nominal-difftime"
jsonSchemaSpec @DiffTime "difftime" jsonSchemaSpec @DiffTime "difftime"
jsonSchemaSpec @Fruit "fruit" jsonSchemaSpec @Fruit "fruit"
jsonSchemaSpec @Shape "shape"
jsonSchemaSpec @Example "example" jsonSchemaSpec @Example "example"
jsonSchemaSpec @Recursive "recursive" jsonSchemaSpec @Recursive "recursive"
jsonSchemaSpec @ListsExample "lists-example" jsonSchemaSpec @ListsExample "lists-example"

View File

@ -100,6 +100,7 @@ spec = do
aesonCodecSpec @DiffTime aesonCodecSpec @DiffTime
aesonCodecSpec @NominalDiffTime aesonCodecSpec @NominalDiffTime
aesonCodecSpec @Fruit aesonCodecSpec @Fruit
aesonCodecSpec @Shape
aesonCodecSpec @Example aesonCodecSpec @Example
aesonCodecErrorSpec @Example "example-error-bool-number" "{\"text\": \"hello\", \"bool\": 5}" aesonCodecErrorSpec @Example "example-error-bool-number" "{\"text\": \"hello\", \"bool\": 5}"
aesonCodecErrorSpec @Example "example-error-fruit-number" "{\"text\": \"hello\", \"bool\": true, \"maybe\": null, \"fruit\": 5}" aesonCodecErrorSpec @Example "example-error-fruit-number" "{\"text\": \"hello\", \"bool\": true, \"maybe\": null, \"fruit\": 5}"

View File

@ -75,6 +75,7 @@ spec = do
nixOptionTypeSpec @NominalDiffTime "nominal-difftime" nixOptionTypeSpec @NominalDiffTime "nominal-difftime"
nixOptionTypeSpec @DiffTime "difftime" nixOptionTypeSpec @DiffTime "difftime"
nixOptionTypeSpec @Fruit "fruit" nixOptionTypeSpec @Fruit "fruit"
nixOptionTypeSpec @Shape "shape"
nixOptionTypeSpec @Example "example" nixOptionTypeSpec @Example "example"
nixOptionsSpec @Example "example" nixOptionsSpec @Example "example"
nixOptionTypeSpec @Recursive "recursive" nixOptionTypeSpec @Recursive "recursive"

View File

@ -97,6 +97,8 @@ spec = do
openAPISchemaSpec @NominalDiffTime "nominal-difftime" openAPISchemaSpec @NominalDiffTime "nominal-difftime"
openAPISchemaSpec @Fruit "fruit" openAPISchemaSpec @Fruit "fruit"
openAPISchemaSpecViaDeclareSchemaRef @Fruit "fruit" openAPISchemaSpecViaDeclareSchemaRef @Fruit "fruit"
openAPISchemaSpec @Shape "shape"
openAPISchemaSpecViaDeclareSchemaRef @Shape "shape"
openAPISchemaSpec @Example "example" openAPISchemaSpec @Example "example"
openAPISchemaSpecViaDeclareSchemaRef @Example "example" openAPISchemaSpecViaDeclareSchemaRef @Example "example"
openAPISchemaSpec @ListsExample "lists-example" openAPISchemaSpec @ListsExample "lists-example"

View File

@ -74,6 +74,7 @@ spec = do
showCodecSpec @TimeOfDay "time-of-day" showCodecSpec @TimeOfDay "time-of-day"
showCodecSpec @ZonedTime "zoned-time" showCodecSpec @ZonedTime "zoned-time"
showCodecSpec @Fruit "fruit" showCodecSpec @Fruit "fruit"
showCodecSpec @Shape "shape"
showCodecSpec @Example "example" showCodecSpec @Example "example"
showCodecSpec @Recursive "recursive" showCodecSpec @Recursive "recursive"
showCodecSpec @ListsExample "lists-example" showCodecSpec @ListsExample "lists-example"

View File

@ -92,6 +92,7 @@ spec = do
swaggerSchemaSpec @DiffTime "difftime" swaggerSchemaSpec @DiffTime "difftime"
swaggerSchemaSpec @NominalDiffTime "nominal-difftime" swaggerSchemaSpec @NominalDiffTime "nominal-difftime"
swaggerSchemaSpec @Fruit "fruit" swaggerSchemaSpec @Fruit "fruit"
swaggerSchemaSpec @Shape "shape"
swaggerSchemaSpec @Example "example" swaggerSchemaSpec @Example "example"
swaggerSchemaSpec @Recursive "recursive" swaggerSchemaSpec @Recursive "recursive"
swaggerSchemaSpec @ListsExample "lists-example" swaggerSchemaSpec @ListsExample "lists-example"

View File

@ -66,6 +66,7 @@ spec = do
yamlSchemaSpec @DiffTime "difftime" yamlSchemaSpec @DiffTime "difftime"
yamlSchemaSpec @NominalDiffTime "nominal-difftime" yamlSchemaSpec @NominalDiffTime "nominal-difftime"
yamlSchemaSpec @Fruit "fruit" yamlSchemaSpec @Fruit "fruit"
yamlSchemaSpec @Shape "shape"
yamlSchemaSpec @Example "example" yamlSchemaSpec @Example "example"
yamlSchemaSpec @Recursive "recursive" yamlSchemaSpec @Recursive "recursive"
yamlSchemaSpec @ListsExample "lists-example" yamlSchemaSpec @ListsExample "lists-example"

View File

@ -84,6 +84,7 @@ spec = do
yamlCodecSpec @DiffTime yamlCodecSpec @DiffTime
yamlCodecSpec @NominalDiffTime yamlCodecSpec @NominalDiffTime
yamlCodecSpec @Fruit yamlCodecSpec @Fruit
yamlCodecSpec @Shape
yamlCodecSpec @Example yamlCodecSpec @Example
yamlCodecSpec @Recursive yamlCodecSpec @Recursive
yamlCodecSpec @MutuallyRecursiveA yamlCodecSpec @MutuallyRecursiveA

View File

@ -59,6 +59,20 @@
}, },
"type": "array" "type": "array"
}, },
"shape": {
"$comment": "shape!?",
"oneOf": [
{
"const": "circle"
},
{
"const": "square"
},
{
"const": "rectangle"
}
]
},
"single-or-list": { "single-or-list": {
"$comment": "an optional list that can also be specified as a single element", "$comment": "an optional list that can also be specified as a single element",
"anyOf": [ "anyOf": [
@ -79,6 +93,7 @@
} }
}, },
"required": [ "required": [
"shape",
"fruit", "fruit",
"maybe", "maybe",
"bool", "bool",

View File

@ -0,0 +1,13 @@
{
"oneOf": [
{
"const": "circle"
},
{
"const": "square"
},
{
"const": "rectangle"
}
]
}

View File

@ -37,6 +37,14 @@
description = "an optional list of texts with a default empty list where the empty list would be omitted"; description = "an optional list of texts with a default empty list where the empty list would be omitted";
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
}; };
shape = lib.mkOption {
description = "shape!?";
type = lib.types.enum [
"circle"
"square"
"rectangle"
];
};
single-or-list = lib.mkOption { single-or-list = lib.mkOption {
default = []; default = [];
description = "an optional list that can also be specified as a single element"; description = "an optional list that can also be specified as a single element";

View File

@ -38,6 +38,14 @@ lib.types.submodule {
description = "an optional list of texts with a default empty list where the empty list would be omitted"; description = "an optional list of texts with a default empty list where the empty list would be omitted";
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
}; };
shape = lib.mkOption {
description = "shape!?";
type = lib.types.enum [
"circle"
"square"
"rectangle"
];
};
single-or-list = lib.mkOption { single-or-list = lib.mkOption {
default = []; default = [];
description = "an optional list that can also be specified as a single element"; description = "an optional list that can also be specified as a single element";

View File

@ -0,0 +1,6 @@
{ lib }:
lib.types.enum [
"circle"
"square"
"rectangle"
]

View File

@ -43,6 +43,15 @@
}, },
"type": "array" "type": "array"
}, },
"shape": {
"description": "shape!?",
"enum": [
"circle",
"square",
"rectangle"
],
"type": "string"
},
"single-or-list": { "single-or-list": {
"additionalProperties": true, "additionalProperties": true,
"anyOf": [ "anyOf": [
@ -68,7 +77,8 @@
"text", "text",
"bool", "bool",
"maybe", "maybe",
"fruit" "fruit",
"shape"
], ],
"type": "object" "type": "object"
} }

View File

@ -0,0 +1,11 @@
{
"definitions": {},
"reference": {
"enum": [
"circle",
"square",
"rectangle"
],
"type": "string"
}
}

View File

@ -44,6 +44,15 @@
}, },
"type": "array" "type": "array"
}, },
"shape": {
"description": "shape!?",
"enum": [
"circle",
"square",
"rectangle"
],
"type": "string"
},
"single-or-list": { "single-or-list": {
"additionalProperties": true, "additionalProperties": true,
"anyOf": [ "anyOf": [
@ -69,7 +78,8 @@
"text", "text",
"bool", "bool",
"maybe", "maybe",
"fruit" "fruit",
"shape"
], ],
"type": "object" "type": "object"
} }

View File

@ -0,0 +1,20 @@
{
"components": {
"schemas": {
"Shape": {
"enum": [
"circle",
"square",
"rectangle"
],
"type": "string"
}
}
},
"info": {
"title": "",
"version": ""
},
"openapi": "3.0.0",
"paths": {}
}

View File

@ -8,93 +8,113 @@ ObjectOfCodec
(ApCodec (ApCodec
(ApCodec (ApCodec
(ApCodec (ApCodec
(BimapCodec (ApCodec
_
_
(RequiredKeyCodec "text" (Just "a text") (StringCodec Nothing)))
(BimapCodec
_ _ (RequiredKeyCodec "bool" (Just "a bool") (BoolCodec Nothing))))
(BimapCodec
_
_
(RequiredKeyCodec
"maybe"
(Just "a maybe text")
(BimapCodec (BimapCodec
_ _
_ _
(EitherCodec (RequiredKeyCodec "text" (Just "a text") (StringCodec Nothing)))
PossiblyJointUnion NullCodec (StringCodec Nothing)))))) (BimapCodec
_ _ (RequiredKeyCodec "bool" (Just "a bool") (BoolCodec Nothing))))
(BimapCodec
_
_
(RequiredKeyCodec
"maybe"
(Just "a maybe text")
(BimapCodec
_
_
(EitherCodec
PossiblyJointUnion NullCodec (StringCodec Nothing))))))
(BimapCodec
_
_
(OptionalKeyCodec
"optional" (Just "an optional text") (StringCodec Nothing))))
(BimapCodec (BimapCodec
_ _
_ _
(OptionalKeyCodec (OptionalKeyCodec
"optional" (Just "an optional text") (StringCodec Nothing)))) "optional-or-null"
(Just "an optional-or-null text")
(BimapCodec
_
_
(EitherCodec
PossiblyJointUnion NullCodec (StringCodec Nothing))))))
(BimapCodec (BimapCodec
_ _
_ _
(OptionalKeyCodec (OptionalKeyWithDefaultCodec
"optional-or-null" "optional-with-default"
(Just "an optional-or-null text") (StringCodec Nothing)
(BimapCodec _
_ (Just "an optional text with a default"))))
_
(EitherCodec
PossiblyJointUnion NullCodec (StringCodec Nothing))))))
(BimapCodec (BimapCodec
_ _
_ _
(OptionalKeyWithDefaultCodec (OptionalKeyWithOmittedDefaultCodec
"optional-with-default" "optional-with-null-default"
(StringCodec Nothing) (BimapCodec _ _ (ArrayOfCodec Nothing (StringCodec Nothing)))
_ _
(Just "an optional text with a default")))) (Just
"an optional list of texts with a default empty list where the empty list would be omitted"))))
(BimapCodec (BimapCodec
_ _
_ _
(OptionalKeyWithOmittedDefaultCodec (OptionalKeyWithOmittedDefaultCodec
"optional-with-null-default" "single-or-list"
(BimapCodec _ _ (ArrayOfCodec Nothing (StringCodec Nothing))) (BimapCodec
_
_
(EitherCodec
PossiblyJointUnion
(StringCodec Nothing)
(BimapCodec _ _ (ArrayOfCodec Nothing (StringCodec Nothing)))))
_ _
(Just (Just
"an optional list of texts with a default empty list where the empty list would be omitted")))) "an optional list that can also be specified as a single element"))))
(BimapCodec (BimapCodec
_ _
_ _
(OptionalKeyWithOmittedDefaultCodec (RequiredKeyCodec
"single-or-list" "fruit"
(Just "fruit!!")
(BimapCodec (BimapCodec
_ _
_ _
(EitherCodec (EitherCodec
PossiblyJointUnion DisjointUnion
(StringCodec Nothing) (BimapCodec _ _ (EqCodec "Apple" (StringCodec Nothing)))
(BimapCodec _ _ (ArrayOfCodec Nothing (StringCodec Nothing))))) (BimapCodec
_ _
(Just _
"an optional list that can also be specified as a single element")))) (EitherCodec
DisjointUnion
(BimapCodec _ _ (EqCodec "Orange" (StringCodec Nothing)))
(BimapCodec
_
_
(EitherCodec
DisjointUnion
(BimapCodec _ _ (EqCodec "Banana" (StringCodec Nothing)))
(BimapCodec _ _ (EqCodec "Melon" (StringCodec Nothing))))))))))))
(BimapCodec (BimapCodec
_ _
_ _
(RequiredKeyCodec (RequiredKeyCodec
"fruit" "shape"
(Just "fruit!!") (Just "shape!?")
(BimapCodec (BimapCodec
_ _
_ _
(EitherCodec (EitherCodec
DisjointUnion DisjointUnion
(BimapCodec _ _ (EqCodec "Apple" (StringCodec Nothing))) (BimapCodec _ _ (EqCodec "circle" (StringCodec Nothing)))
(BimapCodec (BimapCodec
_ _
_ _
(EitherCodec (EitherCodec
DisjointUnion DisjointUnion
(BimapCodec _ _ (EqCodec "Orange" (StringCodec Nothing))) (BimapCodec _ _ (EqCodec "square" (StringCodec Nothing)))
(BimapCodec (BimapCodec _ _ (EqCodec "rectangle" (StringCodec Nothing))))))))))
_
_
(EitherCodec
DisjointUnion
(BimapCodec _ _ (EqCodec "Banana" (StringCodec Nothing)))
(BimapCodec _ _ (EqCodec "Melon" (StringCodec Nothing))))))))))))

View File

@ -0,0 +1,13 @@
BimapCodec
_
_
(EitherCodec
DisjointUnion
(BimapCodec _ _ (EqCodec "circle" (StringCodec Nothing)))
(BimapCodec
_
_
(EitherCodec
DisjointUnion
(BimapCodec _ _ (EqCodec "square" (StringCodec Nothing)))
(BimapCodec _ _ (EqCodec "rectangle" (StringCodec Nothing))))))

View File

@ -39,6 +39,14 @@
}, },
"type": "array" "type": "array"
}, },
"shape": {
"description": "shape!?",
"enum": [
"circle",
"square",
"rectangle"
]
},
"single-or-list": { "single-or-list": {
"additionalProperties": true, "additionalProperties": true,
"description": "an optional list that can also be specified as a single element" "description": "an optional list that can also be specified as a single element"
@ -52,7 +60,8 @@
"text", "text",
"bool", "bool",
"maybe", "maybe",
"fruit" "fruit",
"shape"
], ],
"type": "object" "type": "object"
} }

View File

@ -0,0 +1,17 @@
{
"definitions": {
"Shape": {
"enum": [
"circle",
"square",
"rectangle"
]
}
},
"info": {
"title": "",
"version": ""
},
"paths": {},
"swagger": "2.0"
}

View File

@ -39,3 +39,10 @@
, Banana , Banana
, Melon , Melon
] ]
shape: # required
# shape!?
# one of
[ circle
, square
, rectangle
]

View File

@ -0,0 +1,5 @@
# one of
[ circle
, square
, rectangle
]

View File

@ -1,5 +1,11 @@
# Changelog # Changelog
## [0.4.2.2] - 2024-09-01
### Added
* `boundedEnumCodec`
## [0.4.2.1] - 2024-08-21 ## [0.4.2.1] - 2024-08-21
### Added ### Added

View File

@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
name: autodocodec name: autodocodec
version: 0.4.2.1 version: 0.4.2.2
synopsis: Self-documenting encoder and decoder synopsis: Self-documenting encoder and decoder
homepage: https://github.com/NorfairKing/autodocodec#readme homepage: https://github.com/NorfairKing/autodocodec#readme
bug-reports: https://github.com/NorfairKing/autodocodec/issues bug-reports: https://github.com/NorfairKing/autodocodec/issues

View File

@ -4,7 +4,7 @@
}: }:
mkDerivation { mkDerivation {
pname = "autodocodec"; pname = "autodocodec";
version = "0.4.2.1"; version = "0.4.2.2";
src = ./.; src = ./.;
libraryHaskellDepends = [ libraryHaskellDepends = [
aeson base bytestring containers dlist hashable mtl scientific text aeson base bytestring containers dlist hashable mtl scientific text

View File

@ -1,5 +1,5 @@
name: autodocodec name: autodocodec
version: 0.4.2.1 version: 0.4.2.2
github: "NorfairKing/autodocodec" github: "NorfairKing/autodocodec"
license: MIT license: MIT
author: "Tom Sydney Kerckhove" author: "Tom Sydney Kerckhove"

View File

@ -102,6 +102,7 @@ module Autodocodec
-- *** Enums -- *** Enums
shownBoundedEnumCodec, shownBoundedEnumCodec,
boundedEnumCodec,
stringConstCodec, stringConstCodec,
enumCodec, enumCodec,

View File

@ -1907,6 +1907,33 @@ stringConstCodec =
) )
) )
-- | A codec for a 'Bounded' 'Enum' that uses the provided function to have the values correspond to literal 'Text' values.
--
--
-- === Example usage
--
-- >>> data Fruit = Apple | Orange deriving (Show, Eq, Enum, Bounded)
-- >>> :{
-- let c = boundedEnumCodec $ \case
-- Apple -> "foo"
-- Orange -> "bar"
-- :}
--
-- >>> toJSONVia c Apple
-- String "foo"
-- >>> JSON.parseMaybe (parseJSONVia c) (String "bar") :: Maybe Fruit
-- Just Orange
boundedEnumCodec ::
forall enum.
(Eq enum, Enum enum, Bounded enum) =>
(enum -> T.Text) ->
JSONCodec enum
boundedEnumCodec showFunc =
let ls = [minBound .. maxBound]
in case NE.nonEmpty ls of
Nothing -> error "0 enum values ?!"
Just ne -> stringConstCodec (NE.map (\v -> (v, showFunc v)) ne)
-- | A codec for a 'Bounded' 'Enum' that uses its 'Show' instance to have the values correspond to literal 'Text' values. -- | A codec for a 'Bounded' 'Enum' that uses its 'Show' instance to have the values correspond to literal 'Text' values.
-- --
-- --
@ -1922,11 +1949,7 @@ shownBoundedEnumCodec ::
forall enum. forall enum.
(Show enum, Eq enum, Enum enum, Bounded enum) => (Show enum, Eq enum, Enum enum, Bounded enum) =>
JSONCodec enum JSONCodec enum
shownBoundedEnumCodec = shownBoundedEnumCodec = boundedEnumCodec (T.pack . show)
let ls = [minBound .. maxBound]
in case NE.nonEmpty ls of
Nothing -> error "0 enum values ?!"
Just ne -> stringConstCodec (NE.map (\v -> (v, T.pack (show v))) ne)
-- | Helper function for 'optionalFieldOrNullWith' and 'optionalFieldOrNull'. -- | Helper function for 'optionalFieldOrNullWith' and 'optionalFieldOrNull'.
-- --