Expose ByteString-based text envelope deserialization#1158
Conversation
Add deserialiseFromTextEnvelopeJSON and deserialiseFromTextEnvelopeJSONAnyOf which accept a raw ByteString, enabling text envelope deserialization without file I/O. Refactor readFileTextEnvelope and readFileTextEnvelopeAnyOf to use the new functions.
e03455c to
6ebdec2
Compare
There was a problem hiding this comment.
Pull request overview
Exposes ByteString-based helpers for deserialising text envelopes from JSON, and refactors existing file-based readers to delegate to these helpers.
Changes:
- Adds
deserialiseFromTextEnvelopeJSONanddeserialiseFromTextEnvelopeJSONAnyOf(ByteString →Either TextEnvelopeError …). - Refactors
readFileTextEnvelope/readFileTextEnvelopeAnyOfto reuse the new helpers. - Re-exports the new functions from
Cardano.Api.Serialise.TextEnvelope.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| cardano-api/src/Cardano/Api/Serialise/TextEnvelope/Internal.hs | Introduces new JSON-from-ByteString deserialisers and updates file readers to call them. |
| cardano-api/src/Cardano/Api/Serialise/TextEnvelope.hs | Re-exports the new deserialisation helpers from the public API module. |
| deserialiseFromTextEnvelopeJSON | ||
| :: HasTextEnvelope a | ||
| => ByteString -> Either TextEnvelopeError a | ||
| deserialiseFromTextEnvelopeJSON bs = do | ||
| te <- first TextEnvelopeAesonDecodeError $ Aeson.eitherDecodeStrict' bs | ||
| deserialiseFromTextEnvelope te | ||
|
|
||
| deserialiseFromTextEnvelopeJSONAnyOf | ||
| :: [FromSomeType HasTextEnvelope b] | ||
| -> ByteString | ||
| -> Either TextEnvelopeError b | ||
| deserialiseFromTextEnvelopeJSONAnyOf types bs = do | ||
| te <- first TextEnvelopeAesonDecodeError $ Aeson.eitherDecodeStrict' bs | ||
| deserialiseFromTextEnvelopeAnyOf types te |
There was a problem hiding this comment.
These are new public(-reexported) API functions but they don’t have Haddock. Please add brief Haddock that explains: the input must be a JSON-encoded text envelope (UTF-8), this performs no file I/O, and the error behavior (TextEnvelopeAesonDecodeError for JSON parse failures vs. downstream deserialiseFromTextEnvelope* errors). This helps API consumers choose between readFile* and deserialiseFromTextEnvelopeJSON* correctly.
| deserialiseFromTextEnvelopeJSON bs = do | ||
| te <- first TextEnvelopeAesonDecodeError $ Aeson.eitherDecodeStrict' bs | ||
| deserialiseFromTextEnvelope te |
There was a problem hiding this comment.
The JSON decode step is duplicated in both functions. Consider factoring out a small helper (e.g., decodeTextEnvelopeJSON :: ByteString -> Either TextEnvelopeError TextEnvelope) and then calling deserialiseFromTextEnvelope* on the result. This reduces duplication and keeps future changes to decoding/error-wrapping consistent.
| deserialiseFromTextEnvelopeJSON | ||
| :: HasTextEnvelope a | ||
| => ByteString -> Either TextEnvelopeError a | ||
| deserialiseFromTextEnvelopeJSON bs = do | ||
| te <- first TextEnvelopeAesonDecodeError $ Aeson.eitherDecodeStrict' bs | ||
| deserialiseFromTextEnvelope te | ||
|
|
||
| deserialiseFromTextEnvelopeJSONAnyOf | ||
| :: [FromSomeType HasTextEnvelope b] | ||
| -> ByteString | ||
| -> Either TextEnvelopeError b | ||
| deserialiseFromTextEnvelopeJSONAnyOf types bs = do | ||
| te <- first TextEnvelopeAesonDecodeError $ Aeson.eitherDecodeStrict' bs | ||
| deserialiseFromTextEnvelopeAnyOf types te |
There was a problem hiding this comment.
The JSON decode step is duplicated in both functions. Consider factoring out a small helper (e.g., decodeTextEnvelopeJSON :: ByteString -> Either TextEnvelopeError TextEnvelope) and then calling deserialiseFromTextEnvelope* on the result. This reduces duplication and keeps future changes to decoding/error-wrapping consistent.
| deserialiseFromTextEnvelopeJSON | |
| :: HasTextEnvelope a | |
| => ByteString -> Either TextEnvelopeError a | |
| deserialiseFromTextEnvelopeJSON bs = do | |
| te <- first TextEnvelopeAesonDecodeError $ Aeson.eitherDecodeStrict' bs | |
| deserialiseFromTextEnvelope te | |
| deserialiseFromTextEnvelopeJSONAnyOf | |
| :: [FromSomeType HasTextEnvelope b] | |
| -> ByteString | |
| -> Either TextEnvelopeError b | |
| deserialiseFromTextEnvelopeJSONAnyOf types bs = do | |
| te <- first TextEnvelopeAesonDecodeError $ Aeson.eitherDecodeStrict' bs | |
| deserialiseFromTextEnvelopeAnyOf types te | |
| decodeTextEnvelopeJSON :: ByteString -> Either TextEnvelopeError TextEnvelope | |
| decodeTextEnvelopeJSON bs = | |
| first TextEnvelopeAesonDecodeError $ Aeson.eitherDecodeStrict' bs | |
| deserialiseFromTextEnvelopeJSON | |
| :: HasTextEnvelope a | |
| => ByteString -> Either TextEnvelopeError a | |
| deserialiseFromTextEnvelopeJSON bs = | |
| decodeTextEnvelopeJSON bs >>= deserialiseFromTextEnvelope | |
| deserialiseFromTextEnvelopeJSONAnyOf | |
| :: [FromSomeType HasTextEnvelope b] | |
| -> ByteString | |
| -> Either TextEnvelopeError b | |
| deserialiseFromTextEnvelopeJSONAnyOf types bs = | |
| decodeTextEnvelopeJSON bs >>= deserialiseFromTextEnvelopeAnyOf types |
Extract shared JSON decoding into decodeTextEnvelopeJSON and add Haddock documentation to the new public functions.
Expose ByteString-based text envelope deserialization
Closes #556
Changelog
Context
Addresses #556 — exposes key/text-envelope reading functions that work from a
ByteStringrather than requiring file I/O.Adds two new public functions to
Cardano.Api.Serialise.TextEnvelope:deserialiseFromTextEnvelopeJSON :: HasTextEnvelope a => ByteString -> Either TextEnvelopeError adeserialiseFromTextEnvelopeJSONAnyOf :: [FromSomeType HasTextEnvelope b] -> ByteString -> Either TextEnvelopeError bThese allow callers to deserialize keys (or any text-enveloped value) directly from a
ByteStringwithout going through file I/O. The existingreadFileTextEnvelopeandreadFileTextEnvelopeAnyOfare refactored to use the new functions internally.How to trust this PR
Aeson.eitherDecodeStrict'anddeserialiseFromTextEnvelope/deserialiseFromTextEnvelopeAnyOf.readFile*functions are semantically identical — they just delegate to the new helpers.Checklist