I have compression and decompression function for ZSTD. Somehow after first compressing 7200 bytes of input and then decompressing them returned decompression vector is a bit more than 1MB in size. Both in/out buffers have 1MB size.

void ZipMiniStream::ZipMiniCompressZstd(
        std::function<std::pair<uint64_t, bool>(uint8_t * dst, uint64_t size)> stream_in,
        std::function<void(uint8_t const * dst, uint64_t size)> stream_out,
        uint64_t compression_level) {
    ZSTD_CStream * ctx_ = ZSTD_createCStream();
    ASSERT(ctx_);

    ZSTD_CHECK(ZSTD_initCStream(ctx_, compression_level));

    uint64_t readed_size = 0, ret = 0;
    bool finished = false;
    
    ZSTD_inBuffer in{.src = s_inbuf.data(), .size = s_inbuf.size(), .pos = 0};
    ZSTD_outBuffer out{.dst = s_outbuf.data(), .size = s_outbuf.size(), .pos = 0};
    
    while (true) {
        if (s_inbuf.size() > in.size) {
            std::tie(readed_size, finished) =
                stream_in(s_inbuf.data() + in.size, s_inbuf.size() - in.size);
            in.size += readed_size;
            ASSERT(readed_size > 0 || finished);
        }
        
        ZSTD_CHECK((ret = ZSTD_compressStream2(
            ctx_, &out, &in, finished ? ZSTD_e_end : ZSTD_e_continue)));
        
        if (in.pos > 0) {
            std::memmove(s_inbuf.data(), s_inbuf.data() + in.pos, in.size - in.pos);
            in.size -= in.pos;
            in.pos = 0;
        }
        if (out.pos > 0) {
            stream_out(s_outbuf.data(), out.pos);
            out.pos = 0;
        }
        if (finished && ret == 0) {
            ASSERT(in.size == 0);
            break;
        }
    }
    
    ZSTD_CHECK(ZSTD_freeCStream(ctx_));
}

void ZipMiniStream::ZipMiniDeCompressZstd(
        std::function<std::pair<uint64_t, bool>(uint8_t * dst, uint64_t size)> stream_in,
        std::function<void(uint8_t const * dst, uint64_t size)> stream_out) {
            
    ZSTD_DStream * ctx_ = ZSTD_createDStream();
    ASSERT(ctx_);
    
    ZSTD_CHECK(ZSTD_initDStream(ctx_));
    
    uint64_t readed_size = 0, ret = 0;
    bool finished = false;
    
    ZSTD_inBuffer in{.src = s_inbuf.data(), .size = 0, .pos = 0};
    ZSTD_outBuffer out{.dst = s_outbuf.data(), .size = s_outbuf.size(), .pos = 0};
    
    while (true) {
        if (s_inbuf.size() > in.size) {
            std::tie(readed_size, finished) =
                stream_in(s_inbuf.data() + in.size, s_inbuf.size() - in.size);
            in.size += readed_size;
            ASSERT(readed_size > 0 || finished);
        }
        
        DUMP(in.size); DUMP(in.pos); DUMP(out.size); DUMP(out.pos);
        ZSTD_CHECK((ret = ZSTD_decompressStream(ctx_, &out, &in)));
        DUMP(ret); DUMP(in.size); DUMP(in.pos); DUMP(out.size); DUMP(out.pos);
        
        if (in.pos > 0) {
            std::memmove(s_inbuf.data(), s_inbuf.data() + in.pos, in.size - in.pos);
            in.size -= in.pos;
            in.pos = 0;
        }
        if (out.pos > 0) {
            stream_out(s_outbuf.data(), out.pos);
            out.pos = 0;
        }
        if (finished && ret == 0) {
            ASSERT(in.size == 0);
            break;
        }
    }
    
    ZSTD_CHECK(ZSTD_freeDStream(ctx_));
}