aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/connections/flow.c
blob: 1070c70d4e6a44e2d96eff7dfef54c30c6b0486a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "flow.h"
#include <assert.h>

void pure_transfer_abort(PureTransfer *t) {
    if (!t->active) return;
    PureRelease release = t->release;
    void *owner = t->owner;
    *t = (PureTransfer){0};
    if (release) release(owner);
}

static void advance(PureTransfer *t) {
    while (t->active && t->part < 2 && t->offset == t->spans[t->part].size) {
        t->part++;
        t->offset = 0;
    }
    if (t->active && t->part == 2) pure_transfer_abort(t);
}

void pure_transfer_init(PureTransfer *t, PureSpan header, PureSpan body,
                        void *owner, PureRelease release) {
    assert(!t->active);
    assert((!header.size || header.data) && (!body.size || body.data));
    *t = (PureTransfer){.spans = {header, body}, .owner = owner,
                       .release = release, .active = true};
    advance(t);
}

PureSpan pure_transfer_next(const PureTransfer *t, size_t limit) {
    if (!t->active) return (PureSpan){0};
    PureSpan span = t->spans[t->part];
    size_t remaining = span.size - t->offset;
    return (PureSpan){span.data + t->offset, remaining < limit ? remaining : limit};
}

bool pure_transfer_consume(PureTransfer *t, size_t bytes) {
    if (!t->active || bytes > t->spans[t->part].size - t->offset) return false;
    t->offset += bytes;
    advance(t);
    return true;
}