Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

back_to_the_buffer cannot easily be used recursively #36

Open
Ryuukyu313 opened this issue Jan 27, 2021 · 1 comment
Open

back_to_the_buffer cannot easily be used recursively #36

Ryuukyu313 opened this issue Jan 27, 2021 · 1 comment

Comments

@Ryuukyu313
Copy link
Contributor

As the title says, back_to_the_buffer can not easily be used from within another back_to_the_buffer call, which makes it hard to serialize some nested formats.

The default/recommended way to use back_to_the_buffer would be to use gen(<serializer>) inside the gen closure like in the docs.

back_to_the_buffer(
    4,
    move |buf| gen(string("test"), buf), // < this line
    move |buf, len| gen_simple(be_u32(len as u32), buf)
)

However, this wraps buf in a second WriteContext, so that the serializer is called with a WriteContext<WriteContext<W: Write + BackToTheBuffer>>.
With this, we can no longer call back_to_the_buffer again, since it requires a WriteContext<W: Write + BackToTheBuffer>.

It took me quite a while to come up with this solution: (adapted to the doc example)

back_to_the_buffer(
    4,
    move |buf| {
        let begin = buf.position;
        (string("test")(buf)).map(|wctx| {
            let pos = wctx.position;
            (wctx, pos - begin)
        })
    },
    move |buf, len| gen_simple(be_u32(len as u32), buf)
)

Now back_to_the_buffer could be called again in the stringcombinator.

Could this be fixed/made easier in a nice way?
If not, maybe this example could at least be added to the docs so that others don't run into the same wall as I did.

Thanks!

@str4d
Copy link
Contributor

str4d commented Sep 23, 2021

The above could be turned into a helper function, which would bring things back towards the docs:

fn gen_bttb<W: Write, F: SerializeFn<W>>(
    f: F,
    w: WriteContext<W>,
) -> Result<(WriteContext<W>, u64), GenError> {
    let begin = w.position;
    f(w).map(|wctx| {
        let pos = wctx.position;
        (wctx, pos - begin)
    })
}
back_to_the_buffer(
    4,
    move |buf| gen_bttb(string("test"), buf),
    move |buf, len| gen_simple(be_u32(len as u32), buf)
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants