Skip to content

Commit

Permalink
Implement BCS deserialization from_reader (#6)
Browse files Browse the repository at this point in the history
* Implement BCS deserialization from_reader

** Strategy **
The commit aims to maintain a minimal diff over the previous implementation. To that end, the following changes have been made.
- Make `Deserializer` generic over an inner type `R`
- Factor as much of the implementation as possible into a new trait `BcsReader`, which implements BCS in terms of a few primitive operations. Implement `serde::Deserialize<'de> for Deserializer<R> where Deserializer<R>: BcsReader<'de>`
- Implement `BcsReader<'de>` for `Deserializer<&'de [u8]>` using existing code
- Implement `BcsReader` generically for (a version of) `Deserializer<R: Read>`.

The existing implementation is very close to supporting deserialization from readers. There are only two places in which its behavior relied on access to a byte slice was in the implementation of `de::MapAccess`.

The first case is `map` deserialization. `bcs` needs access to the serialized representation of map keys in order to enforce canonicity. When deserializing from a slice, this is straightforward - the implementation can simply deserialize a map key, and then "look back" at the original input slice to determine its serialized representation. When deserializing from a reader, however, this kind of rewinding is not generally possible. To solve this problem, I introduce a the `TeeReader` struct, which wraps a `Read`er and optionally copies its bytes into a `capture_buffer` for later retrieval. Then, I simply implement `BcsReader` for `Deserializer<TeeReader<...>>`.

The second case is the `end` method, which checks that all input bytes have been consumed. To handle this case, I simply attempt to read one extra byte from the `Read`er after deserialization and assert that an EOF error is returned from the underlying `Read`er.

** Testing **
All existing unit tests except for `zero_copy_parse` have been modified to test that deserialization `from_bytes` and `from_reader` yield the same output. That test is not applicable since readers are not capable of zero-copy deserialization.
  • Loading branch information
preston-evans98 authored Oct 13, 2023
1 parent aef9579 commit 56cfe89
Show file tree
Hide file tree
Showing 5 changed files with 436 additions and 66 deletions.
Loading

0 comments on commit 56cfe89

Please sign in to comment.