multi_compress 0.3.5 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/GET_STARTED.md +188 -0
  4. data/README.md +56 -0
  5. data/db_core/include/mcdb_format.h +55 -0
  6. data/db_core/src/mcdb_format.c +341 -0
  7. data/db_deployment/mysql/Makefile +48 -0
  8. data/db_deployment/mysql/README.md +42 -0
  9. data/db_deployment/mysql/bin/common +160 -0
  10. data/db_deployment/mysql/bin/disable +40 -0
  11. data/db_deployment/mysql/bin/doctor +64 -0
  12. data/db_deployment/mysql/bin/enable +57 -0
  13. data/db_deployment/mysql/bin/install +64 -0
  14. data/db_deployment/mysql/bin/status +65 -0
  15. data/db_deployment/mysql/bin/uninstall +47 -0
  16. data/db_deployment/mysql/bin/upgrade +115 -0
  17. data/db_deployment/mysql/bin/verify +14 -0
  18. data/db_deployment/postgres/Makefile +45 -0
  19. data/db_deployment/postgres/README.md +60 -0
  20. data/db_deployment/postgres/bin/doctor +61 -0
  21. data/db_deployment/postgres/bin/enable +136 -0
  22. data/db_deployment/postgres/bin/install +104 -0
  23. data/db_deployment/postgres/bin/uninstall +54 -0
  24. data/db_deployment/postgres/bin/verify +14 -0
  25. data/docs/database-envelope-v1.md +159 -0
  26. data/exe/multi_compress +228 -0
  27. data/ext/multi_compress/extconf.rb +4 -0
  28. data/ext/multi_compress/multi_compress.c +30 -0
  29. data/lib/multi_compress/active_record.rb +61 -0
  30. data/lib/multi_compress/codec.rb +164 -0
  31. data/lib/multi_compress/database.rb +106 -0
  32. data/lib/multi_compress/db_deployment.rb +456 -0
  33. data/lib/multi_compress/version.rb +1 -1
  34. data/multi_compress.gemspec +55 -0
  35. data/mysql_udf/Makefile +96 -0
  36. data/mysql_udf/README.md +95 -0
  37. data/mysql_udf/sql/examples.sql +11 -0
  38. data/mysql_udf/sql/install.sql +15 -0
  39. data/mysql_udf/sql/uninstall.sql +4 -0
  40. data/mysql_udf/sql/views.sql +8 -0
  41. data/mysql_udf/src/multi_compress_mysql.c +133 -0
  42. data/mysql_udf/src/mysql_udf_abi_57.h +34 -0
  43. data/mysql_udf/test/mcdb_cli.c +60 -0
  44. data/mysql_udf/test/run_e2e.sh +296 -0
  45. data/postgres_extension/Makefile +74 -0
  46. data/postgres_extension/README.md +112 -0
  47. data/postgres_extension/multi_compress.control +4 -0
  48. data/postgres_extension/multi_compress_pg.exports +12 -0
  49. data/postgres_extension/sql/examples.sql +12 -0
  50. data/postgres_extension/sql/multi_compress--0.5.0.sql +24 -0
  51. data/postgres_extension/sql/uninstall.sql +2 -0
  52. data/postgres_extension/sql/views.sql +7 -0
  53. data/postgres_extension/src/mcdb_format.c +2 -0
  54. data/postgres_extension/src/multi_compress_pg.c +96 -0
  55. data/postgres_extension/test/run_e2e.sh +323 -0
  56. metadata +52 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f30991dd0d788507bb43885eacc3ae6c131722b0c77428778e7e3176d6ef220
4
- data.tar.gz: 53ccbd3e9bf75b8b5eb74a8a6d523baab825ec3492ac730dbe2f739732b724e2
3
+ metadata.gz: bc428423e6ad060dd4c421822a586e3a54681019d6e858c88076a5b44868448a
4
+ data.tar.gz: 0d1a9737005c28e2c5580708a94fb2473d5b6f4d7d6fa09281ece76499958f9e
5
5
  SHA512:
6
- metadata.gz: ad1f3ad3d2ba84e5eec72c1c0b5fed2dade4b3f1dd96efc11b6454ec9f9af78e4829e070c7310283d6500ed71a4a9895334a9d91bd6a0c86f4e947a98c5b0706
7
- data.tar.gz: 11369cc33cae0ecb46cf0e9c84e0bc35c72bd2f7cb1cec46425c5cbbc27dfcc9c2037d5e5ab75a4e23c721229577b7ede3aea7bfe7327644024d1be7af229c57
6
+ metadata.gz: bf176d5d014613ae6a0f8bfc3d76869c0ef9a8a72ac19ac6dac39b1ddd11d10f941e350bc5b2f1cd7b7210771ef2fc54e04035b73347d4bc6e67186520a26a0e
7
+ data.tar.gz: ef34ce6bb40e89d16e112e13e95ede1e0bbfe37179556d88e7c4717735d1612c11b0ee216ffc70982417863898a76d2737d1a78c7cffb3bce6a7e916c4746e68
data/CHANGELOG.md CHANGED
@@ -1,5 +1,81 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.0]
4
+
5
+ - MCDB1 now rejects trailing bytes, skippable frames, and concatenated zstd frames.
6
+
7
+ ### Fixed
8
+ - Pin the MySQL 5.7 Docker acceptance target to the official linux/amd64 image digest.
9
+
10
+
11
+ ### Added
12
+ - **Casual database deployment bundles** — `multi_compress db package postgres`
13
+ and `multi_compress db package mysql` build a version-locked tarball directly
14
+ from the installed gem. A DBA extracts it on the database host and uses
15
+ `make verify`, `make doctor`, `sudo make install`, and `make enable` instead
16
+ of cloning the repository or manually locating/copying a `.so`.
17
+ - **Readable-view generator** — `multi_compress db view postgres|mysql` emits
18
+ safely quoted, migration-ready views for DBeaver. MySQL output always converts
19
+ UDF output through `utf8mb4`.
20
+ - **Database envelope v1 (`MCDB1`)** — a frozen, self-describing storage format
21
+ (`docs/database-envelope-v1.md`): 19-byte header (magic/version/codec/flags/
22
+ original_size/crc32) + a zstd frame. zstd-only, UTF-8 text without NUL bytes, 16 MiB cap, no
23
+ dictionaries/base64. Corruption raises in Ruby and PostgreSQL; MySQL returns
24
+ `NULL` and exposes `multi_compress_db_is_valid(blob) = 0` for diagnostics.
25
+ - **`MultiCompress::Database`** — narrow Ruby writer/reader for `MCDB1`
26
+ (`compress`/`decompress`/`valid?`), independent of ActiveRecord. Validates
27
+ UTF-8 and size on write; requires exactly one zstd frame and verifies size +
28
+ CRC-32 on read.
29
+ - **MySQL 5.7 UDF** (`mysql_udf/`) — a separate native target (not built by the
30
+ gem) implementing the same `MCDB1` contract in C over the vendored zstd, with
31
+ `multi_compress_db_version()`, `multi_compress_db_is_valid(blob)`, and
32
+ `multi_compress_db_decompress(blob)`, plus SQL install/uninstall/views,
33
+ a Makefile, a real-MySQL Docker acceptance script, and a Ruby↔C parity
34
+ harness.
35
+ - **PostgreSQL extension** (`postgres_extension/`) — a PGXS target over the
36
+ same shared C decoder, exposing the matching `version`, `is_valid(bytea)`, and
37
+ `decompress(bytea)` SQL functions through `CREATE EXTENSION multi_compress`.
38
+ It includes SQL/view templates and a Docker e2e gate.
39
+ - Golden fixtures (`test/fixtures/database_v1/`) shared by the Ruby tests and the
40
+ C parity harness, proving both implementations agree byte-for-byte.
41
+
42
+ ### Notes
43
+ - The 16 MiB cap and CRC-32 check are enforced identically in Ruby, the MySQL
44
+ UDF, and the PostgreSQL extension. The CRC-32 matches `MultiCompress.crc32`
45
+ (zlib/IEEE). MCDB1 payload text must be valid UTF-8 without NUL bytes so it
46
+ maps safely to PostgreSQL `text`.
47
+ - The ActiveRecord adapter remains experimental pending real Rails integration
48
+ tests; the `MCDB1` path does not depend on it.
49
+
50
+ ## [0.4.0]
51
+
52
+ ### Added
53
+ - **`multi_compress` command-line tool.** Gzip-style file (de)compression with
54
+ `-a/--algo`, `-l/--level`, `-d/--decompress`, `-o`, `-c/--stdout`, `-k/--keep`,
55
+ `-f/--force`, `--max-output`. Streams through `Reader`/`Writer`, writes output
56
+ atomically (temp + fsync + rename, directory fsync before removing the source),
57
+ refuses `input == output` and `-o` with multiple inputs.
58
+ - **`MultiCompress::Codec`** — strict, self-describing compression envelope for
59
+ values stored in a database. Always compresses (one storage format), 7-byte
60
+ magic/version/algo header, strict decode (a corrupt envelope raises
61
+ `DataError`, never silent passthrough), opt-in `legacy:` handling
62
+ (`:reject` default, `:plain`, `{ compressed: :algo }`), `encode: :base64` for
63
+ text columns (explicit `mc1:` prefix), locally-frozen `max_output_size`,
64
+ configurable `encoding:` (validated on write), and optional `serializer:`
65
+ (JSON/Marshal) for non-String values.
66
+ - **ActiveRecord integration** via `MultiCompress::ActiveRecordSupport::Type`
67
+ (for `attribute`) and `::Coder` (for `serialize`). Opt-in `mutable:` enables
68
+ in-place dirty tracking.
69
+
70
+ ### Notes
71
+ - The CLI writes this gem's internal LZ4 block format with the **`.mclz4`**
72
+ extension (not `.lz4`), since it is not interchangeable with the standard
73
+ `lz4` CLI frame.
74
+ - `MultiCompress::Codec` treats one column as one fixed encoding. Use
75
+ `encoding: Encoding::BINARY` (a `:binary`/`bytea` column) for arbitrary bytes.
76
+ - The AR `Type` default does not detect in-place mutation; reassign the
77
+ attribute, or pass `mutable: true`.
78
+
3
79
  ## [0.3.5]
4
80
 
5
81
  ### Changed
data/GET_STARTED.md CHANGED
@@ -862,4 +862,192 @@ puts results
862
862
  # => {:lz4=>{:time=>0.0012, :ratio=>0.234, :size=>1024}, ...}
863
863
  ```
864
864
 
865
+ ## Command-Line Tool
866
+
867
+ Installing the gem provides a `multi_compress` executable (gzip-style):
868
+
869
+ ```bash
870
+ multi_compress file.json # -> file.json.zst (zstd default)
871
+ multi_compress -a brotli -l best a.css # -> a.css.br
872
+ multi_compress -d file.json.zst # -> file.json (algo from extension)
873
+ cat big.log | multi_compress -a zstd -c > big.log.zst # pipe mode
874
+ ```
875
+
876
+ Flags: `-a/--algo` (`zstd|lz4|brotli`), `-l/--level` (number or `fastest|default|best`),
877
+ `-d/--decompress`, `-o/--output`, `-c/--stdout`, `-k/--keep`, `-f/--force`,
878
+ `-q/--quiet`, `--max-output SIZE` (e.g. `64MB`), `--version`.
879
+
880
+ Safety: output is written to a temp file in the destination directory, fsynced,
881
+ atomically renamed, and the directory is fsynced before the source is removed —
882
+ an interrupted run never leaves a partial file or touches the source. The tool
883
+ refuses `input == output` and refuses `-o` with multiple inputs.
884
+
885
+ **LZ4 note:** this gem's LZ4 uses an internal block format that is *not*
886
+ interchangeable with the standard `lz4` CLI. To avoid a false compatibility
887
+ promise, LZ4 output uses the **`.mclz4`** extension; `.lz4` is never produced.
888
+
889
+ ## Database Column Compression
890
+
891
+ There are two intentionally separate database paths:
892
+
893
+ 1. **`MultiCompress::Codec`** is a general application-side envelope for one
894
+ column. It is useful when only Ruby needs to read the data.
895
+ 2. **`MultiCompress::Database` (`MCDB1`)** is the narrow, frozen format for
896
+ MySQL 5.7 or PostgreSQL + DBeaver. It has matching server-side C readers,
897
+ so SQL can decode the BLOB / `bytea`.
898
+
899
+ ### MySQL 5.7 or PostgreSQL / DBeaver: `MultiCompress::Database` (`MCDB1`)
900
+
901
+ Use this path when employees must inspect decoded values in DBeaver, DataGrip,
902
+ or the MySQL console:
903
+
904
+ ```ruby
905
+ require "multi_compress/database"
906
+
907
+ blob = MultiCompress::Database.compress("Привет") # UTF-8 bytes for LONGBLOB / bytea
908
+ text = MultiCompress::Database.decompress(blob) # => "Привет"
909
+ ```
910
+
911
+ MCDB1 is deliberately narrow: zstd only, valid non-NUL UTF-8 text, exactly one
912
+ zstd frame, no dictionaries/Base64, and a 16 MiB decompressed limit.
913
+
914
+ #### 1. Application developer: create the DBA bundle
915
+
916
+ The native reader is intentionally **not** built during `gem install`: it must
917
+ be compiled on the database host, against that host's PostgreSQL/MySQL ABI.
918
+ The developer does not hand a DBA a Git revision or a loose `.so`; they create
919
+ a version-locked source bundle from the installed gem:
920
+
921
+ ```bash
922
+ bundle exec multi_compress db package postgres --output tmp/multi-compress-postgres.tar.gz
923
+ # or
924
+ bundle exec multi_compress db package mysql --output tmp/multi-compress-mysql.tar.gz
925
+ ```
926
+
927
+ The archive contains the shared MCDB1 decoder, the right server-side source,
928
+ vendored zstd, checksum manifest, and a small `Makefile`/installer. It is the
929
+ only artifact the DBA needs.
930
+
931
+ #### 2. DBA: install and enable on the database server
932
+
933
+ PostgreSQL, on the PostgreSQL host:
934
+
935
+ ```bash
936
+ tar -xzf multi-compress-postgres.tar.gz
937
+ cd multi_compress-postgres-0.5.0
938
+ make verify
939
+ make doctor
940
+ sudo make install
941
+ sudo -u postgres make enable DB=app_production \
942
+ MIGRATION_ROLE=app_migrations READ_ROLE=dbeaver_readonly
943
+ ```
944
+
945
+ `install` builds `multi_compress_pg.so` on that host, discovers paths through
946
+ `pg_config`, and installs the library/control/extension SQL. Install the matching
947
+ `postgresql-server-dev-<major>` package and a C toolchain first; `make doctor`
948
+ checks those prerequisites before changing the server. `enable` runs
949
+ `CREATE EXTENSION` in exactly one database. Repeat `make enable DB=...` for
950
+ reporting databases or any separate database that must query MCDB1 columns.
951
+
952
+ MySQL 5.7, on the MySQL host:
953
+
954
+ ```bash
955
+ tar -xzf multi-compress-mysql.tar.gz
956
+ cd multi_compress-mysql-0.5.0
957
+ make verify
958
+ make doctor MYSQL_DEFAULTS_FILE=/etc/mysql/admin.cnf
959
+ sudo make install MYSQL_DEFAULTS_FILE=/etc/mysql/admin.cnf
960
+ make enable MYSQL_DEFAULTS_FILE=/etc/mysql/admin.cnf
961
+ ```
962
+
963
+ The MySQL installer verifies the local server is MySQL 5.7, asks that same
964
+ server for `@@plugin_dir`, builds the UDF locally, and installs the library
965
+ there. `enable` registers the functions once for that MySQL server.
966
+
967
+ #### 3. Application developer: commit the readable view
968
+
969
+ Do not ask DBAs or DBeaver users to type decoder calls. Generate a safe,
970
+ quoted view definition and commit it as a Rails migration or versioned SQL:
971
+
972
+ ```bash
973
+ bundle exec multi_compress db view postgres \
974
+ --table app.events \
975
+ --column payload_compressed \
976
+ --view admin.events_readable \
977
+ --columns id,created_at,status \
978
+ --as payload \
979
+ --output db/views/events_readable.sql
980
+ ```
981
+
982
+ For MySQL use `db view mysql` with the same arguments. The MySQL definition
983
+ includes `CONVERT(... USING utf8mb4)`, so Cyrillic, Kazakh text and emoji are
984
+ returned correctly to DBeaver. If PostgreSQL was enabled in a non-default schema,
985
+ pass `--extension-schema that_schema` to the PostgreSQL view generator.
986
+
987
+ DBeaver users now make ordinary queries against the view:
988
+
989
+ ```sql
990
+ SELECT id, created_at, status, payload
991
+ FROM admin.events_readable
992
+ WHERE id = 123;
993
+ ```
994
+
995
+ The view decompresses selected rows. Filter by indexed, uncompressed fields
996
+ before reading it; do not perform unbounded `LIKE '%text%'` searches on the
997
+ decoded payload.
998
+
999
+ The shared, long-term format contract is
1000
+ [`docs/database-envelope-v1.md`](docs/database-envelope-v1.md).
1001
+
1002
+ ### General Ruby-side `Codec`
1003
+
1004
+ `MultiCompress::Codec` transparently compresses on write and "unwraps" on read,
1005
+ with a strict, self-describing envelope suitable for persistent storage.
1006
+
1007
+ ```ruby
1008
+ require "multi_compress/codec"
1009
+
1010
+ codec = MultiCompress::Codec.new(algo: :zstd, level: 6)
1011
+ blob = codec.dump(big_json) # always-compressed envelope for a :binary column
1012
+ json = codec.load(blob) # exact original string back (UTF-8 by default)
1013
+ ```
1014
+
1015
+ Guarantees: always one compressed format (no mixed raw/compressed rows); a
1016
+ recognized-but-corrupt envelope raises `MultiCompress::DataError` (never silent
1017
+ data loss); invalid encoding is rejected at **write** time; the decompression
1018
+ cap is frozen locally so global config can't loosen it.
1019
+
1020
+ Options: `encode: :base64` (for text/varchar columns; prefer `:binary`/`bytea`),
1021
+ `serializer:` (JSON or Marshal for non-String values), `encoding:`
1022
+ (default UTF-8; use `Encoding::BINARY` for arbitrary bytes), `max_output_size:`,
1023
+ `dictionary:`, and `legacy:` for reading pre-existing values:
1024
+
1025
+ ```ruby
1026
+ MultiCompress::Codec.new(legacy: :reject) # default: no envelope -> raise
1027
+ MultiCompress::Codec.new(legacy: :plain) # treat as uncompressed string
1028
+ MultiCompress::Codec.new(legacy: { compressed: :zstd }) # decompress old raw blobs
1029
+ ```
1030
+
1031
+ ### ActiveRecord (experimental)
1032
+
1033
+ Requires ActiveModel. The adapter has unit coverage but must still be integration-tested
1034
+ against each Rails/database combination before being treated as a stable deployment contract. Register the type (`attribute`) or use a coder (`serialize`):
1035
+
1036
+ ```ruby
1037
+ require "multi_compress/active_record"
1038
+
1039
+ class Event < ApplicationRecord
1040
+ # attribute API (prefer a :binary / bytea column)
1041
+ attribute :payload, MultiCompress::ActiveRecordSupport::Type.new(algo: :zstd, level: 6)
1042
+
1043
+ # or the serialize macro with JSON objects
1044
+ # serialize :payload, coder: MultiCompress::ActiveRecordSupport::Coder.new(algo: :zstd, serializer: JSON)
1045
+ end
1046
+ ```
1047
+
1048
+ Dirty tracking: by default in-place mutation isn't detected — reassign the
1049
+ attribute (`event.payload = event.payload.merge(...)`) or pass `mutable: true`
1050
+ to the `Type` to enable `changed_in_place?` (which decompresses the old value
1051
+ on each check).
1052
+
865
1053
  This guide covers comprehensive usage of the MultiCompress gem. For advanced use cases or questions, see the source code or create an issue on GitHub.
data/README.md CHANGED
@@ -172,6 +172,62 @@ Or use the build script:
172
172
  ./build.sh
173
173
  ```
174
174
 
175
+ ## Command-line tool & DB column compression
176
+
177
+ Installing the gem provides a gzip-style `multi_compress` executable:
178
+
179
+ ```bash
180
+ multi_compress file.json # -> file.json.zst
181
+ multi_compress -d file.json.zst # -> file.json
182
+ cat big.log | multi_compress -a zstd -c > big.log.zst
183
+ ```
184
+
185
+ `MultiCompress::Codec` is a general-purpose application-side envelope for a
186
+ single database column (optional ActiveRecord `Type`/`Coder` adapters and
187
+ optional Base64 for text columns). It is **not** the format for SQL-side
188
+ inspection.
189
+
190
+ For MySQL 5.7 or PostgreSQL + DBeaver, use the separate, frozen `MCDB1` API instead:
191
+
192
+ ```ruby
193
+ require "multi_compress/database"
194
+
195
+ blob = MultiCompress::Database.compress("JSON or UTF-8 text") # store in LONGBLOB / bytea
196
+ text = MultiCompress::Database.decompress(blob)
197
+ ```
198
+
199
+ For database-side reading, the installed gem creates a **self-contained DBA
200
+ bundle** from the exact gem version — no Git clone, manual `.so` copy, or
201
+ hand-written extension SQL:
202
+
203
+ ```bash
204
+ bundle exec multi_compress db package postgres --output tmp/multi-compress-postgres.tar.gz
205
+ # or
206
+ bundle exec multi_compress db package mysql --output tmp/multi-compress-mysql.tar.gz
207
+ ```
208
+
209
+ The DBA extracts that archive on the database host and runs `make verify`,
210
+ `make doctor`, and `sudo make install`. PostgreSQL enablement also requires the
211
+ migration and read roles; MySQL uses a local Unix socket and has explicit
212
+ `upgrade`, `disable`, and `uninstall` confirmations. The bundle compiles the
213
+ native reader against that host's real PostgreSQL/MySQL environment and installs
214
+ it into the server-reported directory. Generate the DBeaver-facing read view
215
+ from the application repository as well:
216
+
217
+ ```bash
218
+ bundle exec multi_compress db view postgres \
219
+ --table app.events --column payload_compressed \
220
+ --view admin.events_readable --columns id,created_at,status \
221
+ --output db/views/events_readable.sql
222
+ ```
223
+
224
+ Use `--extension-schema NAME` with the PostgreSQL view generator only when the
225
+ DBA enabled the extension outside the default `multi_compress` schema. See
226
+ [GET_STARTED.md](GET_STARTED.md#database-column-compression) for the full
227
+ app-server → DBA → DBeaver flow.
228
+
229
+ > The CLI writes this gem's internal LZ4 format as `.mclz4` (not `.lz4`), since it is not interchangeable with the standard `lz4` CLI.
230
+
175
231
  ## Requirements
176
232
 
177
233
  - Ruby >= 2.7.1
@@ -0,0 +1,55 @@
1
+ #ifndef MCDB_FORMAT_H
2
+ #define MCDB_FORMAT_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ #define MCDB_MAGIC0 0x4D /* 'M' */
8
+ #define MCDB_MAGIC1 0x43 /* 'C' */
9
+ #define MCDB_MAGIC2 0x44 /* 'D' */
10
+ #define MCDB_MAGIC3 0x42 /* 'B' */
11
+
12
+ #define MCDB_VERSION 1
13
+ #define MCDB_CODEC_ZSTD 1
14
+ #define MCDB_FLAGS_V1 0
15
+ #define MCDB_HEADER_SIZE 19
16
+ #define MCDB_CRC_OFFSET 15
17
+ #define MCDB_MAX_OUTPUT (16u * 1024u * 1024u) /* 16 MiB decompressed */
18
+ #define MCDB_MAX_ENVELOPE 16842771u
19
+
20
+ #define MCDB_ERRLEN 256
21
+ #define MCDB_READER_VERSION "0.5.0"
22
+
23
+ typedef enum {
24
+ MCDB_OK = 0,
25
+ MCDB_ERR_TRUNCATED,
26
+ MCDB_ERR_ENVELOPE_SIZE,
27
+ MCDB_ERR_MAGIC,
28
+ MCDB_ERR_VERSION,
29
+ MCDB_ERR_CODEC,
30
+ MCDB_ERR_FLAGS,
31
+ MCDB_ERR_SIZE_LIMIT,
32
+ MCDB_ERR_DECOMPRESS,
33
+ MCDB_ERR_TRAILING_DATA,
34
+ MCDB_ERR_FRAME_CONTENT_SIZE,
35
+ MCDB_ERR_SIZE_MISMATCH,
36
+ MCDB_ERR_CRC,
37
+ MCDB_ERR_UTF8,
38
+ MCDB_ERR_ALLOC
39
+ } mcdb_status;
40
+
41
+ mcdb_status mcdb_validate_header(const unsigned char *in, size_t in_len,
42
+ uint64_t *out_original_size);
43
+
44
+ /* The caller must validate the header and size out from it before calling. */
45
+ mcdb_status mcdb_decode_into(const unsigned char *in, size_t in_len,
46
+ unsigned char *out, size_t out_capacity,
47
+ size_t *out_len, char *errbuf);
48
+
49
+ mcdb_status mcdb_decode(const unsigned char *in, size_t in_len,
50
+ unsigned char **out, size_t *out_len,
51
+ char *errbuf);
52
+
53
+ const char *mcdb_status_str(mcdb_status s);
54
+
55
+ #endif