Repository: WasmEdge/WasmEdge
Pull request #4124: refactor(example): migrate zlib example to use WIT
Author: login: PhantomInTheWire
Labels: name: c-Example
name: v-0.15.0
Created: 2025-05-26T15:46:57Z | Merged: 2025-05-31T23:27:09Z

This PR refactors the existing `plugin/wasmedge-zlib` example to use WebAssembly Interface Types (WIT) instead of the older interface.

### Motivation

The `main.cpp` in the example already included a `TODO` to migrate this example to WIT. This PR implements that migration, improves modularity, and adds a Makefile to simplify build steps.

### Changes

- Refactored the zlib example to use WIT.
- Added Makefile to simplify the build steps.
- Updated the README with new usage instructions.

### Notes

- This is my first contribution to WasmEdge
- I did not open a separate issue since the task was already mentioned as a TODO in the code itself.

Let me know if anything needs to be changed!


Diff:
diff --git a/examples/plugin/wasmedge-zlib/.gitignore b/examples/plugin/wasmedge-zlib/.gitignore
index 567609b1234a..21ab3076fd41 100644
--- a/examples/plugin/wasmedge-zlib/.gitignore
+++ b/examples/plugin/wasmedge-zlib/.gitignore
@@ -1 +1,2 @@
 build/
+bindings/
diff --git a/examples/plugin/wasmedge-zlib/Makefile b/examples/plugin/wasmedge-zlib/Makefile
new file mode 100644
index 000000000000..7d64f37afda6
--- /dev/null
+++ b/examples/plugin/wasmedge-zlib/Makefile
@@ -0,0 +1,168 @@
+.PHONY: help
+help:
+	@echo "📘 Makefile Help"
+	@echo ""
+	@echo "Available targets:"
+	@echo "  all              - Run tool checks and build both native and WASM targets"
+	@echo "  check-all-tools  - Check all required tools for bindings, native, wasm, and runner"
+	@echo "  check-bindings   - Check required tools for binding generation"
+	@echo "  check-native     - Check tools required for native build"
+	@echo "  check-wasm       - Check tools required for wasm build"
+	@echo "  check-run-wasm   - Check Wasm runner (wasmedge)"
+	@echo "  native           - Build the native executable"
+	@echo "  run-native       - Run the native executable"
+	@echo "  wasm             - Build the WebAssembly module"
+	@echo "  run-wasm         - Run the WebAssembly module with WasmEdge"
+	@echo "  clean            - Remove all build and generated files"
+	@echo "  help             - Show this help message"
+
+# -------- Configuration --------
+WIT_FOLDER := wit
+BINDINGS_DIR := bindings
+BINDINGS_C := $(BINDINGS_DIR)/zlib_component.c
+BINDINGS_H := $(BINDINGS_DIR)/zlib_component.h
+BINDINGS_COMPONENT_TYPE_O := $(BINDINGS_DIR)/zlib_component_component_type.o
+MAIN_CPP := main.cpp
+
+BUILD_NATIVE_DIR := build/native
+BUILD_WASM_DIR := build/wasm
+NATIVE_EXE := $(BUILD_NATIVE_DIR)/zlib_test_native
+WASM_EXE := $(BUILD_WASM_DIR)/main.wasm
+
+CFLAGS := -O2 -Wall -Wextra
+CPPFLAGS := -std=c++17
+LDFLAGS_NATIVE := -lz
+
+# -------- Compiler Detection --------
+ifeq (, $(shell which clang))
+	CC := gcc
+	CXX := g++
+else
+	CC := clang
+	CXX := clang++
+endif
+
+# -------- Dependency Lists --------
+DEPS_BINDING := wit-bindgen awk
+DEPS_NATIVE  := $(CC) $(CXX) awk
+DEPS_WASM    := emcc em++ awk
+DEPS_RUN_WASM := wasmedge
+
+# -------- WIT Source Files --------
+WIT_FILES := $(shell find $(WIT_FOLDER) -name '*.wit' -print 2>/dev/null)
+ifeq ($(strip $(WIT_FILES)),)
+  WIT_SOURCES := $(WIT_FOLDER)
+else
+  WIT_SOURCES := $(WIT_FILES)
+endif
+
+# -------- Default Target --------
+all: check-all-tools native wasm
+
+# -------- Dependency Checks --------
+.PHONY: check-bindings check-native check-wasm check-run-wasm check-all-tools
+check-bindings:
+	@echo "🔍 Checking binding-generation tools..."
+	@for cmd in $(DEPS_BINDING); do \
+	  command -v $$cmd >/dev/null 2>&1 || { echo "Error: '$$cmd' not found in PATH."; exit 1; }; \
+	done
+	@echo "✔️  Binding tools OK."
+
+check-native:
+	@echo "🔍 Checking native-build tools..."
+	@for cmd in $(DEPS_NATIVE); do \
+	  command -v $$cmd >/dev/null 2>&1 || { echo "Error: '$$cmd' not found in PATH."; exit 1; }; \
+	done
+	@echo "✔️  Native build tools OK."
+
+check-wasm:
+	@echo "🔍 Checking wasm-build tools..."
+	@for cmd in $(DEPS_WASM); do \
+	  command -v $$cmd >/dev/null 2>&1 || { echo "Error: '$$cmd' not found in PATH."; exit 1; }; \
+	done
+	@echo "✔️  Wasm build tools OK."
+
+check-run-wasm:
+	@echo "🔍 Checking Wasm runner..."
+	@for cmd in $(DEPS_RUN_WASM); do \
+	  command -v $$cmd >/dev/null 2>&1 || { echo "Error: '$$cmd' not found in PATH."; exit 1; }; \
+	done
+	@echo "✔️  Wasm runner OK."
+
+check-all-tools: check-bindings check-native check-wasm check-run-wasm
+
+# -------- Binding Generation & Sanitization --------
+$(BINDINGS_C) $(BINDINGS_H) $(BINDINGS_COMPONENT_TYPE_O): $(WIT_SOURCES)
+	@$(MAKE) -s check-bindings
+	@echo "Generating WIT bindings (produces .c, .h, component_type.o)..."
+	mkdir -p $(BINDINGS_DIR)
+	wit-bindgen c $(WIT_FOLDER) --out-dir $(BINDINGS_DIR)
+	@echo "Sanitizing export names in $(BINDINGS_C)..."
+	@awk -v sanitize_chars_regex='[:/@#%.]' '\
+	{\
+		line = $$0; processed_line = 0;\
+		prefix_end_marker = "__export_name__(\"";\
+		start_pos = index(line, prefix_end_marker);\
+		if (start_pos > 0) {\
+			name_start_pos = start_pos + length(prefix_end_marker);\
+			name_and_suffix_part = substr(line, name_start_pos);\
+			closing_quote_pos_in_suffix = index(name_and_suffix_part, "\"");\
+			if (closing_quote_pos_in_suffix > 0) {\
+				name_to_sanitize = substr(name_and_suffix_part, 1, closing_quote_pos_in_suffix - 1);\
+				prefix = substr(line, 1, name_start_pos - 1);\
+				suffix = substr(name_and_suffix_part, closing_quote_pos_in_suffix);\
+				sanitized_name = name_to_sanitize;\
+				gsub(sanitize_chars_regex, "_", sanitized_name);\
+				print prefix sanitized_name suffix;\
+				processed_line = 1;\
+			}\
+		}\
+		if (processed_line == 0) print line;\
+	}' $(BINDINGS_C) > $(BINDINGS_C).tmp && mv $(BINDINGS_C).tmp $(BINDINGS_C)
+
+# -------- Native Build --------
+native: check-native $(NATIVE_EXE)
+
+$(BUILD_NATIVE_DIR)/main_native.o: $(MAIN_CPP)
+	mkdir -p $(BUILD_NATIVE_DIR)
+	$(CXX) $(CFLAGS) $(CPPFLAGS) -c $(MAIN_CPP) -o $@
+
+$(NATIVE_EXE): $(BUILD_NATIVE_DIR)/main_native.o
+	@echo "Building native executable..."
+	$(CXX) $^ -o $@ $(LDFLAGS_NATIVE)
+	@echo "✔️  Native build complete: $@"
+
+.PHONY: run-native
+run-native: $(NATIVE_EXE)
+	@echo "▶️  Running native executable..."
+	$(NATIVE_EXE)
+
+# -------- WASM Build --------
+wasm: check-wasm $(WASM_EXE)
+
+$(BUILD_WASM_DIR)/main.o: $(MAIN_CPP) $(BINDINGS_H)
+	mkdir -p $(BUILD_WASM_DIR)
+	em++ $(CFLAGS) -sWARN_ON_UNDEFINED_SYMBOLS=0 $(CPPFLAGS) -I$(BINDINGS_DIR) -c $(MAIN_CPP) -o $@
+
+$(BUILD_WASM_DIR)/zlib_component_bindings.o: $(BINDINGS_C) $(BINDINGS_H)
+	mkdir -p $(BUILD_WASM_DIR)
+	emcc $(CFLAGS) -sWARN_ON_UNDEFINED_SYMBOLS=0 -I$(BINDINGS_DIR) -c $(BINDINGS_C) -o $@
+
+$(WASM_EXE): $(BUILD_WASM_DIR)/main.o $(BUILD_WASM_DIR)/zlib_component_bindings.o $(BINDINGS_COMPONENT_TYPE_O)
+	@echo "Building WebAssembly module..."
+	em++ $(CFLAGS) -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0 \
+		$(BUILD_WASM_DIR)/main.o \
+		$(BUILD_WASM_DIR)/zlib_component_bindings.o \
+		$(BINDINGS_COMPONENT_TYPE_O) \
+		-o $@
+	@echo "✔️  WASM build complete: $@"
+
+.PHONY: run-wasm
+run-wasm: check-run-wasm wasm
+	@echo "▶️  Running WebAssembly module via WasmEdge..."
+	wasmedge $(WASM_EXE)
+
+# -------- Clean --------
+.PHONY: clean
+clean:
+	rm -rf $(BUILD_NATIVE_DIR) $(BUILD_WASM_DIR) $(BINDINGS_DIR)
diff --git a/examples/plugin/wasmedge-zlib/README.md b/examples/plugin/wasmedge-zlib/README.md
index 8ae2dcfd1b98..f100de458e37 100644
--- a/examples/plugin/wasmedge-zlib/README.md
+++ b/examples/plugin/wasmedge-zlib/README.md
@@ -4,6 +4,24 @@ This is an example to demonstrate how to use the `wasmedge-zlib` plugin of WasmE
 
 ## Prerequisites
 
+You need four main components:
+
+1. Emscripten SDK (for compiling to WebAssembly)
+
+2. WasmEdge Runtime
+
+3. wasmedge-zlib plugin 
+
+4. wit-bindgen(v0.42.x) (for generating bindings on the fly)
+
+### Check missing
+
+
+The project includes a Makefile that can check for dependencies
+```bash
+make check-all-tools
+```
+
 ### Install Emscripten SDK (C++ Compiler Toolkit for wasm targets)
 
 ```bash
@@ -18,7 +36,7 @@ source ./emsdk_env.sh # Only this shell will be able to use emscripten.
 
 ### Install WasmEdge and WASMEDGE-zlib plugin
 
-Note that if you install WasmEdge using the install script, you need to download `wasmedge-zlib` plugin from the [release page](https://github.com/WasmEdge/WasmEdge/releases/) and put it into `$HOME/.wasmedge/plugin/`.
+**Note**: If you install WasmEdge using the installation script, you need to download `wasmedge-zlib` plugin from the [release page](https://github.com/WasmEdge/WasmEdge/releases/) and put it into `$HOME/.wasmedge/plugin/`.
 
 Or you can build Wasmedge from scratch with `wasmedge-zlib` plugin enabled.
 
@@ -36,30 +54,99 @@ cmake --build . -j
 # Compiled Wasmedge is located in ./tools/wasmedge/wasmedge
 ```
 
-## Build and Run the example as a WASM Module
+## Build and Run the example using Make
+
+```bash
+cd ./examples/plugin/wasmedge-zlib/
+make all # Build both native and WebAssembly versions
+make clean # Clean the build directory
+make native # Build the native version
+make wasm # Build WebAssembly version
+make run-native # Run the native version
+make run-wasm # Run the WebAssembly version
+make help # Show all available targets
+```
+
+## Manually Build and Run the example as a WASM Module
+
+#### First generate the bindings
 
 ```bash
 cd ../examples/plugin/wasmedge-zlib/
-mkdir build
-em++ main.cpp -O2 -o build/main.wasm -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0
+mkdir -p bindings
+wit-bindgen c wit --out-dir bindings
+```
+
+#### Sanitize the .c file
+
+**NOTE**: The bindings/zlib_component.c file generated by wit-bindgen has a lot of #, @, and . characters in the function signatures and that Emscripten doesn't like.
+
+```bash
+awk -v sanitize_chars_regex='[:/@#%.]' '
+{
+  line = $0; processed_line = 0;
+  prefix_end_marker = "__export_name__(\"";
+  start_pos = index(line, prefix_end_marker);
+  if (start_pos > 0) {
+    name_start_pos = start_pos + length(prefix_end_marker);
+    name_and_suffix_part = substr(line, name_start_pos);
+    closing_quote_pos_in_suffix = index(name_and_suffix_part, "\"");
+    if (closing_quote_pos_in_suffix > 0) {
+      name_to_sanitize = substr(name_and_suffix_part, 1, closing_quote_pos_in_suffix - 1);
+      prefix = substr(line, 1, name_start_pos - 1);
+      suffix = substr(name_and_suffix_part, closing_quote_pos_in_suffix);
+      sanitized_name = name_to_sanitize;
+      gsub(sanitize_chars_regex, "_", sanitized_name);
+      print prefix sanitized_name suffix;
+      processed_line = 1;
+    }
+  }
+  if (processed_line == 0) print line;
+}' bindings/zlib_component.c > bindings/zlib_component.c.tmp && mv bindings/zlib_component.c.tmp bindings/zlib_component.c
+```
+
+#### Build and Link the wasm
+
+```bash
+mkdir -p build/wasm
+
+# Compile C++ source
+em++ -O2 -std=c++17 -Wall -Wextra \
+  -sWARN_ON_UNDEFINED_SYMBOLS=0 \
+  -Ibindings \
+  -c main.cpp -o build/wasm/main.o
+
+# Compile generated bindings
+emcc -O2 -Wall -Wextra \
+  -sWARN_ON_UNDEFINED_SYMBOLS=0 \
+  -Ibindings \
+  -c bindings/zlib_component.c -o build/wasm/zlib_component_bindings.o
+
+# Link with bindings component_type.o
+em++ -O2 -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0 \
+  build/wasm/main.o \
+  build/wasm/zlib_component_bindings.o \
+  bindings/zlib_component_component_type.o \
+  -o build/wasm/main.wasm
 ```
 
-Then we get `build/main.wasm`.
+Then we get `build/wasm/main.wasm`.
 
 We can run this example with `Wasmedge` with the following command
 
 ```bash
-../../../build/tools/wasmedge/wasmedge build/main.wasm
+wasmedge build/wasm/main.wasm
 ```
 
-## Build and Run the example as a Native executable
+## Manually Build and Run the example as a Native executable
 
 ```bash
-apt install zlib1g-dev # For Ubuntu / Debian distros | Try zlib-devel for fedora
+apt install zlib1g-dev # For Ubuntu / Debian distros | Try zlib-devel for fedora | Try `brew install zlib` for macOS
 cd ../examples/plugin/wasmedge-zlib/
-mkdir build
-g++ main.cpp -o build/main -lz
-./build/main
+mkdir -p build/native
+g++ -O2 -std=c++17 -Wall -Wextra \
+main.cpp -o build/native/zlib_test_native -lz
+./build/native/zlib_test_native
 ```
 
 ## Expected Output
diff --git a/examples/plugin/wasmedge-zlib/main.cpp b/examples/plugin/wasmedge-zlib/main.cpp
index a9b764bad27d..32ed84d2f2f8 100644
--- a/examples/plugin/wasmedge-zlib/main.cpp
+++ b/examples/plugin/wasmedge-zlib/main.cpp
@@ -1,238 +1,346 @@
 #include <algorithm>
-#include <cstddef>
-#include <cstdint>
 #include <cstdlib>
-#include <cstring>
+#include <ctime>
 #include <iostream>
-#include <iterator>
-#include <random>
-#include <type_traits>
 #include <vector>
 
-// ----------------------------------------------------------
-// TODO: LOOK FOR A .WIT REPLACEMENT
-
-#ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#define PRESERVE EMSCRIPTEN_KEEPALIVE
-#define IMPORT __attribute__((import_module("wasmedge_zlib"))) extern "C"
-#else
+// For native use the zlib library
+#ifndef __EMSCRIPTEN__
 #include <zlib.h>
-#define PRESERVE
-#define IMPORT extern "C"
 #endif
 
+// Include the wit-bindgen generated header only for Emscripten(wasm) builds.
 #ifdef __EMSCRIPTEN__
+#include "bindings/zlib_component.h"
+#endif
 
-#define ZLIB_VERSION "1.2.11"
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_STREAM_ERROR (-2)
-#define Z_FINISH 4
-#define Z_NULL NULL
-
-typedef void *(*alloc_func)(void *opaque, unsigned int items,
-                            unsigned int size);
-typedef void (*free_func)(void *opaque, void *address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-  unsigned char *next_in; /* next input byte */
-  uint32_t avail_in;      /* number of bytes available at next_in */
-  unsigned long total_in; /* total number of input bytes read so far */
-
-  unsigned char *next_out; /* next output byte will go here */
-  uint32_t avail_out;      /* remaining free space at next_out */
-  unsigned long total_out; /* total number of bytes output so far */
-
-  char *msg;                    /* last error message, NULL if no error */
-  struct internal_state *state; /* not visible by applications */
-
-  alloc_func zalloc; /* used to allocate the internal state */
-  free_func zfree;   /* used to free the internal state */
-  void *opaque;      /* private data object passed to zalloc and zfree */
-
-  int data_type;       /* best guess about the data type: binary or text
-                          for deflate, or the decoding state for inflate */
-  unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */
-  unsigned long reserved; /* reserved for future use */
-} z_stream;
+// NOTE: Some function signatures, structs etc need to be same as the ones in
+// zlib_component.h example: `bool exports_example_zlib_compressor_deflate(...)`
+// This is to ensure that the C ABI layer can call these functions correctly.
+// This is also true for some extern "C" functions.
 
-IMPORT int deflateInit_(z_stream *strm, int level, const char *version,
-                        int stream_size);
-IMPORT int inflateInit_(z_stream *strm, const char *version, int stream_size);
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ZLIB Function Implementations
+// These are used by the test() function directly.
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+extern "C" {
+#ifdef __EMSCRIPTEN__
+// Wasm imports for Emscripten builds
+__attribute__((import_module("wasmedge_zlib"))) int32_t compress(
+    uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen);
 
-#define deflateInit(strm, level)                                               \
-  deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#define inflateInit(strm)                                                      \
-  inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+__attribute__((import_module("wasmedge_zlib"))) int32_t uncompress(
+    uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen);
 
-IMPORT int deflate(z_stream *strm, int flush);
-IMPORT int inflate(z_stream *strm, int flush);
+// Define our internal compress/uncompress to call the Wasm imports
+int32_t zlibCustomCompress(uint8_t *Dest, size_t *DestLen,
+                           const uint8_t *Source, size_t SourceLen) {
+  return compress(Dest, DestLen, Source, SourceLen);
+}
+int32_t zlibCustomUncompress(uint8_t *Dest, size_t *DestLen,
+                             const uint8_t *Source, size_t SourceLen) {
+  return uncompress(Dest, DestLen, Source, SourceLen);
+}
 
-IMPORT int deflateEnd(z_stream *strm);
-IMPORT int inflateEnd(z_stream *strm);
+#else
+// Native zlib wrapper functions
+int32_t zlibCustomCompress(uint8_t *Dest, size_t *DestLen,
+                           const uint8_t *Source, size_t SourceLen) {
+  uLongf ZDestLen = *DestLen;
+  int Ret = ::compress(Dest, &ZDestLen, Source, (uLong)SourceLen);
+  if (Ret == Z_OK) {
+    *DestLen = (size_t)ZDestLen;
+    return 0;
+  }
+  return Ret;
+}
 
+int32_t zlibCustomUncompress(uint8_t *Dest, size_t *DestLen,
+                             const uint8_t *Source, size_t SourceLen) {
+  uLongf ZDestLen = *DestLen;
+  int Ret = ::uncompress(Dest, &ZDestLen, Source, (uLong)SourceLen);
+  if (Ret == Z_OK) {
+    *DestLen = (size_t)ZDestLen;
+    return 0;
+  }
+  return Ret;
+}
 #endif
+} // extern "C"
 
-// ----------------------------------------------------------
-
-static constexpr size_t DataSize = 1 * 1024 * 1024;
-
-constexpr auto RandChar = []() -> char {
-  constexpr char Charset[] = "0123456789"
-                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                             "abcdefghijklmnopqrstuvwxyz";
-  constexpr size_t MaxIndex = (sizeof(Charset) - 1);
-  return Charset[rand() % MaxIndex];
-};
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// WIT-bindgen C ABI Layer Implementation
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#ifdef __EMSCRIPTEN__
 
-void *CustomMalloc(void *Opaque, unsigned int Items, unsigned int Size) {
+static std::string formatErrorHelper(const char *Prefix, int32_t Code) {
+  return std::string(Prefix) + std::to_string(Code);
+}
 
-  auto Add = malloc(Items * Size);
-  std::cout << "zalloc : " << Add << " = " << Items * Size << std::endl;
-  return Add;
+extern "C" {
+
+// canonical_abi_realloc and canonical_abi_free are required by wit-bindgen
+// generated code.
+__attribute__((export_name("canonical_abi_realloc"))) void *
+canonical_abi_realloc(void *old_ptr, size_t old_size, size_t align,
+                      size_t new_size) {
+  (void)old_size;
+  (void)align;
+  if (new_size == 0) {
+    if (old_ptr) {
+      free(old_ptr);
+    }
+    return nullptr;
+  }
+  void *new_ptr = realloc(old_ptr, new_size);
+  if (new_ptr == nullptr && new_size > 0) {
+    fprintf(stderr,
+            "FATAL: canonical_abi_realloc failed to allocate %zu bytes.\n",
+            new_size);
+  }
+  return new_ptr;
 }
 
-void CustomFree(void *Opaque, void *Address) {
-  std::cout << "zfree : " << Address << std::endl;
+__attribute__((export_name("canonical_abi_free"))) void
+canonical_abi_free(void *ptr, size_t size, size_t align) {
+  (void)size;
+  (void)align;
+  if (ptr) {
+    free(ptr);
+  }
+}
 
-  free(Address);
+// Helper function to convert std::vector<uint8_t> to zlib_component_list_u8_t
+static void vecToListU8(const std::vector<uint8_t> &Vec,
+                        zlib_component_list_u8_t *List) {
+  if (Vec.empty()) {
+    List->ptr = nullptr;
+    List->len = 0;
+    return;
+  }
+  List->ptr =
+      static_cast<uint8_t *>(canonical_abi_realloc(nullptr, 0, 1, Vec.size()));
+  if (List->ptr) {
+    memcpy(List->ptr, Vec.data(), Vec.size());
+    List->len = Vec.size();
+  } else {
+    List->len = 0; // Allocation failed
+    fprintf(stderr, "ABI Layer Error: Memory allocation failed for list_u8_t "
+                    "conversion.\n");
+  }
 }
 
-int InitDeflateZStream(z_stream &Strm, int Level) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
+// Helper function to convert std::string to zlib_component_string_t
+static void strToComponentString(const std::string &Str,
+                                 zlib_component_string_t *CompStr) {
+  if (Str.empty()) {
+    CompStr->ptr = nullptr;
+    CompStr->len = 0;
+    return;
+  }
+  CompStr->ptr = static_cast<uint8_t *>(
+      canonical_abi_realloc(nullptr, 0, 1, Str.length()));
+  if (CompStr->ptr) {
+    memcpy(CompStr->ptr, Str.data(), Str.length());
+    CompStr->len = Str.length();
+  } else {
+    CompStr->len = 0; // Allocation failed
+    fprintf(
+        stderr,
+        "ABI Layer Error: Memory allocation failed for string conversion.\n");
+  }
+}
 
-  int Ret = deflateInit(&Strm, Level);
+bool exports_example_zlib_compressor_deflate(zlib_component_list_u8_t *input,
+                                             zlib_component_list_u8_t *ret_ok,
+                                             zlib_component_string_t *ret_err) {
+  std::vector<uint8_t> SourceData;
+  if (input->len > 0) {
+    if (input->ptr == nullptr) {
+      std::string ErrMsg =
+          "Invalid input to deflate: non-zero length with null pointer.";
+      strToComponentString(ErrMsg, ret_err);
+      ret_ok->ptr = nullptr;
+      ret_ok->len = 0;
+      return false;
+    }
+    SourceData.assign(input->ptr, input->ptr + input->len);
+  }
 
-  if (Ret != Z_OK) {
-    std::cerr << "'deflateInit' failed!" << std::endl;
-    std::terminate();
+  if (SourceData.empty()) {
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
   }
 
-  return Ret;
-}
+  size_t DestLenEstimate = SourceData.size() * 2;
+  if (DestLenEstimate < 128)
+    DestLenEstimate = 128;
 
-int InitInflateZStream(z_stream &Strm) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
+  std::vector<uint8_t> CompressedData(DestLenEstimate);
+  size_t ActualDestLen = DestLenEstimate;
 
-  int Ret = inflateInit(&Strm);
+  int32_t ResultCode = zlibCustomCompress(CompressedData.data(), &ActualDestLen,
+                                          SourceData.data(), SourceData.size());
 
-  if (Ret != Z_OK) {
-    std::cerr << "'inflateInit' failed!" << std::endl;
-    std::terminate();
+  if (ResultCode == 0) { // Success
+    CompressedData.resize(ActualDestLen);
+    vecToListU8(CompressedData, ret_ok);
+    if (ActualDestLen > 0 && ret_ok->ptr == nullptr && ret_ok->len == 0) {
+      strToComponentString("Memory allocation failed for deflate Ok value.",
+                           ret_err);
+      return false;
+    }
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  } else {
+    strToComponentString(
+        formatErrorHelper("Compression failed with error code: ", ResultCode),
+        ret_err);
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    return false;
   }
-
-  return Ret;
 }
 
-template <typename T>
-std::vector<unsigned char> Deflate(const std::vector<T> &Source,
-                                   int Level = -1) {
-
-  int Ret;
-  z_stream Strm;
-  Ret = InitDeflateZStream(Strm, Level);
-  const std::size_t SrcSize = Source.size() * sizeof(T);
-  std::size_t OutBufferSize = SrcSize / 3 + 16;
-  std::vector<unsigned char> OutBuffer(OutBufferSize, {});
-
-  Strm.avail_in = SrcSize;
-  Strm.next_in = reinterpret_cast<unsigned char *>(
-      const_cast<std::remove_const_t<T> *>(Source.data()));
-  Strm.avail_out = OutBuffer.size();
-  Strm.next_out = OutBuffer.data();
-
-  do {
-
-    if (Strm.avail_out == 0) {
-      const std::size_t ExtensionSize = SrcSize / 3 + 16;
-      Strm.avail_out = ExtensionSize;
-      OutBuffer.resize(OutBufferSize + ExtensionSize, {});
-      Strm.next_out = std::next(OutBuffer.data(), OutBufferSize);
-      OutBufferSize += ExtensionSize;
+bool exports_example_zlib_compressor_inflate(zlib_component_list_u8_t *input,
+                                             zlib_component_list_u8_t *ret_ok,
+                                             zlib_component_string_t *ret_err) {
+  std::vector<uint8_t> SourceData;
+  if (input->len > 0) {
+    if (input->ptr == nullptr) {
+      std::string ErrMsg =
+          "Invalid input to inflate: non-zero length with null pointer.";
+      strToComponentString(ErrMsg, ret_err);
+      ret_ok->ptr = nullptr;
+      ret_ok->len = 0;
+      return false;
     }
+    SourceData.assign(input->ptr, input->ptr + input->len);
+  }
 
-    Ret = deflate(&Strm, Z_FINISH);
+  if (SourceData.empty()) {
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  }
 
-    if (Ret == Z_STREAM_ERROR) {
-      std::cerr << "Zlib Stream Error!" << std::endl;
-      std::terminate();
-    }
-  } while (Ret != Z_STREAM_END);
+  size_t DestLenEstimate = SourceData.size() * 4;
+  if (DestLenEstimate < 1024)
+    DestLenEstimate = 1024;
+  if (SourceData.size() > (512 * 1024) &&
+      DestLenEstimate < SourceData.size() * 8) {
+    DestLenEstimate = SourceData.size() * 8;
+  }
 
-  deflateEnd(&Strm);
-  OutBuffer.resize(OutBufferSize - Strm.avail_out);
+  std::vector<uint8_t> DecompressedData(DestLenEstimate);
+  size_t ActualDestLen = DestLenEstimate;
 
-  return OutBuffer;
-}
+  int32_t ResultCode =
+      zlibCustomUncompress(DecompressedData.data(), &ActualDestLen,
+                           SourceData.data(), SourceData.size());
 
-template <typename T>
-std::vector<T> Inflate(const std::vector<unsigned char> &Source) {
-
-  int Ret;
-  z_stream Strm;
-  Ret = InitInflateZStream(Strm);
-  const std::size_t SrcSize = Source.size();
-  std::size_t OutBufferSize = SrcSize / 3 + 16;
-  std::vector<unsigned char> OutBuffer(OutBufferSize, {});
-
-  Strm.avail_in = SrcSize;
-  Strm.next_in = const_cast<unsigned char *>(Source.data());
-  Strm.avail_out = OutBuffer.size();
-  Strm.next_out = OutBuffer.data();
-
-  do {
-
-    if (Strm.avail_out == 0) {
-      const std::size_t ExtensionSize = SrcSize / 3 + 16;
-      Strm.avail_out = ExtensionSize;
-      OutBuffer.resize(OutBufferSize + ExtensionSize, {});
-      Strm.next_out = std::next(OutBuffer.data(), OutBufferSize);
-      OutBufferSize += ExtensionSize;
+  if (ResultCode == -5 /* Z_BUF_ERROR */ && ActualDestLen == DestLenEstimate) {
+    size_t LargerDestLenEstimate = DestLenEstimate;
+    if (SourceData.size() * 10 > LargerDestLenEstimate) {
+      LargerDestLenEstimate = SourceData.size() * 10;
+    } else {
+      LargerDestLenEstimate *= 2;
     }
-
-    Ret = inflate(&Strm, Z_FINISH);
-
-    if (Ret == Z_STREAM_ERROR) {
-      std::cerr << "Zlib Stream Error!" << std::endl;
-      std::terminate();
+    const size_t MaxDecompressionBuffer = 256 * 1024 * 1024;
+    if (LargerDestLenEstimate > MaxDecompressionBuffer) {
+      LargerDestLenEstimate = MaxDecompressionBuffer;
     }
-  } while (Ret != Z_STREAM_END);
 
-  inflateEnd(&Strm);
-  OutBufferSize -= Strm.avail_out;
-
-  std::vector<T> RetBuffer(reinterpret_cast<T *>(OutBuffer.data()),
-                           std::next(reinterpret_cast<T *>(OutBuffer.data()),
-                                     (OutBufferSize / sizeof(T))));
+    if (LargerDestLenEstimate > DestLenEstimate) {
+      fprintf(stderr,
+              "Decompression: Z_BUF_ERROR, retrying with larger buffer: %zu "
+              "bytes (previous: %zu)\n",
+              LargerDestLenEstimate, DestLenEstimate);
+      DecompressedData.resize(LargerDestLenEstimate);
+      ActualDestLen = LargerDestLenEstimate;
+      ResultCode = zlibCustomUncompress(DecompressedData.data(), &ActualDestLen,
+                                        SourceData.data(), SourceData.size());
+    }
+  }
 
-  return RetBuffer;
+  if (ResultCode == 0) { // Success
+    DecompressedData.resize(ActualDestLen);
+    vecToListU8(DecompressedData, ret_ok);
+    if (ActualDestLen > 0 && ret_ok->ptr == nullptr && ret_ok->len == 0) {
+      strToComponentString("Memory allocation failed for inflate Ok value.",
+                           ret_err);
+      return false;
+    }
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  } else {
+    strToComponentString(
+        formatErrorHelper("Decompression failed with error code: ", ResultCode),
+        ret_err);
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    return false;
+  }
 }
 
+} // extern "C"
+#endif // __EMSCRIPTEN__
+
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Test function and main
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 int test() {
-  std::vector<char> Data(DataSize, {});
-  std::generate_n(std::begin(Data), DataSize, RandChar);
+  const size_t DataSize = 1 * 1024 * 1024;
+  std::vector<uint8_t> Data(DataSize);
+  std::generate(Data.begin(), Data.end(), []() -> uint8_t {
+    constexpr char Charset[] = "0123456789"
+                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                               "abcdefghijklmnopqrstuvwxyz";
+    constexpr size_t MaxIndex = (sizeof(Charset) - 1);
+    return static_cast<uint8_t>(Charset[rand() % MaxIndex]);
+  });
 
   std::cout << "Compressing Buffer of size : " << DataSize << "B" << std::endl;
-  const auto CompressedBuffer = Deflate(Data, 6);
-
-  std::cout << "Decompressing Buffer of size : " << CompressedBuffer.size()
-            << "B" << std::endl;
-  const auto DecompressedBuffer = Inflate<char>(CompressedBuffer);
 
-  auto CompareResult = Data == DecompressedBuffer;
-  std::cout << (CompareResult ? "Success" : "Fail") << std::endl;
+  // Test compression
+  size_t CompressedSize = DataSize * 2;
+  std::vector<uint8_t> Compressed(CompressedSize);
+  // Use zlibCustomCompress
+  int32_t Result = zlibCustomCompress(Compressed.data(), &CompressedSize,
+                                      Data.data(), Data.size());
+  if (Result != 0) {
+    std::cerr << "Compression failed with error code: " << Result << std::endl;
+    return 1;
+  }
+  Compressed.resize(CompressedSize);
+
+  std::cout << "Decompressing Buffer of size : " << Compressed.size() << "B"
+            << std::endl;
+
+  // Test decompression
+  size_t DecompressedSize = DataSize;
+  std::vector<uint8_t> Decompressed(DecompressedSize);
+
+  // Use zlibCustomUncompress
+  Result = zlibCustomUncompress(Decompressed.data(), &DecompressedSize,
+                                Compressed.data(), Compressed.size());
+  if (Result != 0) {
+    std::cerr << "Decompression failed with error code: " << Result
+              << std::endl;
+    return 1;
+  }
+  Decompressed.resize(DecompressedSize);
 
-  return CompareResult;
+  bool const Success = (Data == Decompressed);
+  std::cout << (Success ? "Success" : "Fail") << std::endl;
+  return Success ? 0 : 1;
 }
 
-int main() {
-  test();
-  return 0;
-}
+int main() { return test(); }
diff --git a/examples/plugin/wasmedge-zlib/wit/world.wit b/examples/plugin/wasmedge-zlib/wit/world.wit
new file mode 100644
index 000000000000..c02e0c318aa6
--- /dev/null
+++ b/examples/plugin/wasmedge-zlib/wit/world.wit
@@ -0,0 +1,5 @@
+package example:zlib@0.1.0;
+
+world zlib-component {
+    export compressor;
+}
diff --git a/examples/plugin/wasmedge-zlib/wit/zlib.wit b/examples/plugin/wasmedge-zlib/wit/zlib.wit
new file mode 100644
index 000000000000..1f6a7f357b56
--- /dev/null
+++ b/examples/plugin/wasmedge-zlib/wit/zlib.wit
@@ -0,0 +1,18 @@
+// Define the interface that our Wasm module will export.
+interface compressor {
+    /// Compresses a list of bytes using a deflate-like algorithm.
+    ///
+    /// Takes a list of bytes as input.
+    /// Returns a result:
+    /// - Ok: a list of compressed bytes.
+    /// - Err: a string describing the error.
+    deflate: func(input: list<u8>) -> result<list<u8>, string>;
+
+    /// Decompresses a list of bytes using an inflate-like algorithm.
+    ///
+    /// Takes a list of (presumably) compressed bytes as input.
+    /// Returns a result:
+    /// - Ok: a list of decompressed bytes.
+    /// - Err: a string describing the error.
+    inflate: func(input: list<u8>) -> result<list<u8>, string>;
+}


Reviews:
user: login: hydai
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-27T07:02:46Z
user: login: PhantomInTheWire
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T07:42:17Z
user: login: PhantomInTheWire
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T07:42:53Z
user: login: hydai
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-27T07:44:21Z
user: login: hydai
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-31T18:59:04Z
user: login: PhantomInTheWire
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T19:19:48Z
user: login: hydai
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-31T19:20:56Z
user: login: PhantomInTheWire
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T19:33:50Z
user: login: PhantomInTheWire
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T22:01:29Z
user: login: PhantomInTheWire
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-31T22:01:55Z
user: login: hydai
body: LGTM.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-31T22:28:48Z
user: login: hydai
body: Blocked due to the lint issue.
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-31T22:33:14Z
user: login: hydai
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-31T23:26:52Z

Review comments:
diff_hunk: @@ -1,238 +1,86 @@
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
-#include <cstdlib>
 #include <cstring>
 #include <iostream>
-#include <iterator>
-#include <random>
-#include <type_traits>
 #include <vector>
 
-// ----------------------------------------------------------
-// TODO: LOOK FOR A .WIT REPLACEMENT
-
+// Import declarations for wasmedge_zlib plugin
+extern "C" {
+    // Compression functions
 #ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#define PRESERVE EMSCRIPTEN_KEEPALIVE
-#define IMPORT __attribute__((import_module("wasmedge_zlib"))) extern "C"
-#else
-#include <zlib.h>
-#define PRESERVE
-#define IMPORT extern "C"
+    __attribute__((import_module("wasmedge_zlib")))
 #endif
+    int32_t compress(uint8_t* dest, size_t* destLen, const uint8_t* source, size_t sourceLen);
 
 #ifdef __EMSCRIPTEN__
-
-#define ZLIB_VERSION "1.2.11"
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_STREAM_ERROR (-2)
-#define Z_FINISH 4
-#define Z_NULL NULL
-
-typedef void *(*alloc_func)(void *opaque, unsigned int items,
-                            unsigned int size);
-typedef void (*free_func)(void *opaque, void *address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-  unsigned char *next_in; /* next input byte */
-  uint32_t avail_in;      /* number of bytes available at next_in */
-  unsigned long total_in; /* total number of input bytes read so far */
-
-  unsigned char *next_out; /* next output byte will go here */
-  uint32_t avail_out;      /* remaining free space at next_out */
-  unsigned long total_out; /* total number of bytes output so far */
-
-  char *msg;                    /* last error message, NULL if no error */
-  struct internal_state *state; /* not visible by applications */
-
-  alloc_func zalloc; /* used to allocate the internal state */
-  free_func zfree;   /* used to free the internal state */
-  void *opaque;      /* private data object passed to zalloc and zfree */
-
-  int data_type;       /* best guess about the data type: binary or text
-                          for deflate, or the decoding state for inflate */
-  unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */
-  unsigned long reserved; /* reserved for future use */
-} z_stream;
-
-IMPORT int deflateInit_(z_stream *strm, int level, const char *version,
-                        int stream_size);
-IMPORT int inflateInit_(z_stream *strm, const char *version, int stream_size);
-
-#define deflateInit(strm, level)                                               \
-  deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#define inflateInit(strm)                                                      \
-  inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
-
-IMPORT int deflate(z_stream *strm, int flush);
-IMPORT int inflate(z_stream *strm, int flush);
-
-IMPORT int deflateEnd(z_stream *strm);
-IMPORT int inflateEnd(z_stream *strm);
-
+    __attribute__((import_module("wasmedge_zlib")))
 #endif
-
-// ----------------------------------------------------------
-
-static constexpr size_t DataSize = 1 * 1024 * 1024;
-
-constexpr auto RandChar = []() -> char {
-  constexpr char Charset[] = "0123456789"
-                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                             "abcdefghijklmnopqrstuvwxyz";
-  constexpr size_t MaxIndex = (sizeof(Charset) - 1);
-  return Charset[rand() % MaxIndex];
-};
-
-void *CustomMalloc(void *Opaque, unsigned int Items, unsigned int Size) {
-
-  auto Add = malloc(Items * Size);
-  std::cout << "zalloc : " << Add << " = " << Items * Size << std::endl;
-  return Add;
+    int32_t uncompress(uint8_t* dest, size_t* destLen, const uint8_t* source, size_t sourceLen);
 }
 
-void CustomFree(void *Opaque, void *Address) {
-  std::cout << "zfree : " << Address << std::endl;
-
-  free(Address);
-}
-
-int InitDeflateZStream(z_stream &Strm, int Level) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
-
-  int Ret = deflateInit(&Strm, Level);
+// WIT interface implementation functions
path: examples/plugin/wasmedge-zlib/main.cpp
user: login: hydai
body: Is this part generated from the WIT file? If so, how can I do it?
created_at: 2025-05-27T07:02:39Z
author_association: MEMBER
diff_hunk: @@ -1,238 +1,86 @@
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
-#include <cstdlib>
 #include <cstring>
 #include <iostream>
-#include <iterator>
-#include <random>
-#include <type_traits>
 #include <vector>
 
-// ----------------------------------------------------------
-// TODO: LOOK FOR A .WIT REPLACEMENT
-
+// Import declarations for wasmedge_zlib plugin
+extern "C" {
+    // Compression functions
 #ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#define PRESERVE EMSCRIPTEN_KEEPALIVE
-#define IMPORT __attribute__((import_module("wasmedge_zlib"))) extern "C"
-#else
-#include <zlib.h>
-#define PRESERVE
-#define IMPORT extern "C"
+    __attribute__((import_module("wasmedge_zlib")))
 #endif
+    int32_t compress(uint8_t* dest, size_t* destLen, const uint8_t* source, size_t sourceLen);
 
 #ifdef __EMSCRIPTEN__
-
-#define ZLIB_VERSION "1.2.11"
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_STREAM_ERROR (-2)
-#define Z_FINISH 4
-#define Z_NULL NULL
-
-typedef void *(*alloc_func)(void *opaque, unsigned int items,
-                            unsigned int size);
-typedef void (*free_func)(void *opaque, void *address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-  unsigned char *next_in; /* next input byte */
-  uint32_t avail_in;      /* number of bytes available at next_in */
-  unsigned long total_in; /* total number of input bytes read so far */
-
-  unsigned char *next_out; /* next output byte will go here */
-  uint32_t avail_out;      /* remaining free space at next_out */
-  unsigned long total_out; /* total number of bytes output so far */
-
-  char *msg;                    /* last error message, NULL if no error */
-  struct internal_state *state; /* not visible by applications */
-
-  alloc_func zalloc; /* used to allocate the internal state */
-  free_func zfree;   /* used to free the internal state */
-  void *opaque;      /* private data object passed to zalloc and zfree */
-
-  int data_type;       /* best guess about the data type: binary or text
-                          for deflate, or the decoding state for inflate */
-  unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */
-  unsigned long reserved; /* reserved for future use */
-} z_stream;
-
-IMPORT int deflateInit_(z_stream *strm, int level, const char *version,
-                        int stream_size);
-IMPORT int inflateInit_(z_stream *strm, const char *version, int stream_size);
-
-#define deflateInit(strm, level)                                               \
-  deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#define inflateInit(strm)                                                      \
-  inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
-
-IMPORT int deflate(z_stream *strm, int flush);
-IMPORT int inflate(z_stream *strm, int flush);
-
-IMPORT int deflateEnd(z_stream *strm);
-IMPORT int inflateEnd(z_stream *strm);
-
+    __attribute__((import_module("wasmedge_zlib")))
 #endif
-
-// ----------------------------------------------------------
-
-static constexpr size_t DataSize = 1 * 1024 * 1024;
-
-constexpr auto RandChar = []() -> char {
-  constexpr char Charset[] = "0123456789"
-                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                             "abcdefghijklmnopqrstuvwxyz";
-  constexpr size_t MaxIndex = (sizeof(Charset) - 1);
-  return Charset[rand() % MaxIndex];
-};
-
-void *CustomMalloc(void *Opaque, unsigned int Items, unsigned int Size) {
-
-  auto Add = malloc(Items * Size);
-  std::cout << "zalloc : " << Add << " = " << Items * Size << std::endl;
-  return Add;
+    int32_t uncompress(uint8_t* dest, size_t* destLen, const uint8_t* source, size_t sourceLen);
 }
 
-void CustomFree(void *Opaque, void *Address) {
-  std::cout << "zfree : " << Address << std::endl;
-
-  free(Address);
-}
-
-int InitDeflateZStream(z_stream &Strm, int Level) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
-
-  int Ret = deflateInit(&Strm, Level);
+// WIT interface implementation functions
path: examples/plugin/wasmedge-zlib/main.cpp
user: login: PhantomInTheWire
body: No, it’s handwritten since this is a simple example with two functions, not generated. If you want autogenerated bindings, you can:
```bash
wit-bindgen c wit/ --out-dir bindings/
```
and use it something like this
```cpp
#include "bindings/wasmedge_zlib.h"
```
created_at: 2025-05-27T07:42:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,238 +1,86 @@
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
-#include <cstdlib>
 #include <cstring>
 #include <iostream>
-#include <iterator>
-#include <random>
-#include <type_traits>
 #include <vector>
 
-// ----------------------------------------------------------
-// TODO: LOOK FOR A .WIT REPLACEMENT
-
+// Import declarations for wasmedge_zlib plugin
+extern "C" {
+    // Compression functions
 #ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#define PRESERVE EMSCRIPTEN_KEEPALIVE
-#define IMPORT __attribute__((import_module("wasmedge_zlib"))) extern "C"
-#else
-#include <zlib.h>
-#define PRESERVE
-#define IMPORT extern "C"
+    __attribute__((import_module("wasmedge_zlib")))
 #endif
+    int32_t compress(uint8_t* dest, size_t* destLen, const uint8_t* source, size_t sourceLen);
 
 #ifdef __EMSCRIPTEN__
-
-#define ZLIB_VERSION "1.2.11"
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_STREAM_ERROR (-2)
-#define Z_FINISH 4
-#define Z_NULL NULL
-
-typedef void *(*alloc_func)(void *opaque, unsigned int items,
-                            unsigned int size);
-typedef void (*free_func)(void *opaque, void *address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-  unsigned char *next_in; /* next input byte */
-  uint32_t avail_in;      /* number of bytes available at next_in */
-  unsigned long total_in; /* total number of input bytes read so far */
-
-  unsigned char *next_out; /* next output byte will go here */
-  uint32_t avail_out;      /* remaining free space at next_out */
-  unsigned long total_out; /* total number of bytes output so far */
-
-  char *msg;                    /* last error message, NULL if no error */
-  struct internal_state *state; /* not visible by applications */
-
-  alloc_func zalloc; /* used to allocate the internal state */
-  free_func zfree;   /* used to free the internal state */
-  void *opaque;      /* private data object passed to zalloc and zfree */
-
-  int data_type;       /* best guess about the data type: binary or text
-                          for deflate, or the decoding state for inflate */
-  unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */
-  unsigned long reserved; /* reserved for future use */
-} z_stream;
-
-IMPORT int deflateInit_(z_stream *strm, int level, const char *version,
-                        int stream_size);
-IMPORT int inflateInit_(z_stream *strm, const char *version, int stream_size);
-
-#define deflateInit(strm, level)                                               \
-  deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#define inflateInit(strm)                                                      \
-  inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
-
-IMPORT int deflate(z_stream *strm, int flush);
-IMPORT int inflate(z_stream *strm, int flush);
-
-IMPORT int deflateEnd(z_stream *strm);
-IMPORT int inflateEnd(z_stream *strm);
-
+    __attribute__((import_module("wasmedge_zlib")))
 #endif
-
-// ----------------------------------------------------------
-
-static constexpr size_t DataSize = 1 * 1024 * 1024;
-
-constexpr auto RandChar = []() -> char {
-  constexpr char Charset[] = "0123456789"
-                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                             "abcdefghijklmnopqrstuvwxyz";
-  constexpr size_t MaxIndex = (sizeof(Charset) - 1);
-  return Charset[rand() % MaxIndex];
-};
-
-void *CustomMalloc(void *Opaque, unsigned int Items, unsigned int Size) {
-
-  auto Add = malloc(Items * Size);
-  std::cout << "zalloc : " << Add << " = " << Items * Size << std::endl;
-  return Add;
+    int32_t uncompress(uint8_t* dest, size_t* destLen, const uint8_t* source, size_t sourceLen);
 }
 
-void CustomFree(void *Opaque, void *Address) {
-  std::cout << "zfree : " << Address << std::endl;
-
-  free(Address);
-}
-
-int InitDeflateZStream(z_stream &Strm, int Level) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
-
-  int Ret = deflateInit(&Strm, Level);
+// WIT interface implementation functions
path: examples/plugin/wasmedge-zlib/main.cpp
user: login: PhantomInTheWire
body: should i change the example to use auto-generated bindings?
created_at: 2025-05-27T07:42:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,238 +1,86 @@
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
-#include <cstdlib>
 #include <cstring>
 #include <iostream>
-#include <iterator>
-#include <random>
-#include <type_traits>
 #include <vector>
 
-// ----------------------------------------------------------
-// TODO: LOOK FOR A .WIT REPLACEMENT
-
+// Import declarations for wasmedge_zlib plugin
+extern "C" {
+    // Compression functions
 #ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#define PRESERVE EMSCRIPTEN_KEEPALIVE
-#define IMPORT __attribute__((import_module("wasmedge_zlib"))) extern "C"
-#else
-#include <zlib.h>
-#define PRESERVE
-#define IMPORT extern "C"
+    __attribute__((import_module("wasmedge_zlib")))
 #endif
+    int32_t compress(uint8_t* dest, size_t* destLen, const uint8_t* source, size_t sourceLen);
 
 #ifdef __EMSCRIPTEN__
-
-#define ZLIB_VERSION "1.2.11"
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_STREAM_ERROR (-2)
-#define Z_FINISH 4
-#define Z_NULL NULL
-
-typedef void *(*alloc_func)(void *opaque, unsigned int items,
-                            unsigned int size);
-typedef void (*free_func)(void *opaque, void *address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-  unsigned char *next_in; /* next input byte */
-  uint32_t avail_in;      /* number of bytes available at next_in */
-  unsigned long total_in; /* total number of input bytes read so far */
-
-  unsigned char *next_out; /* next output byte will go here */
-  uint32_t avail_out;      /* remaining free space at next_out */
-  unsigned long total_out; /* total number of bytes output so far */
-
-  char *msg;                    /* last error message, NULL if no error */
-  struct internal_state *state; /* not visible by applications */
-
-  alloc_func zalloc; /* used to allocate the internal state */
-  free_func zfree;   /* used to free the internal state */
-  void *opaque;      /* private data object passed to zalloc and zfree */
-
-  int data_type;       /* best guess about the data type: binary or text
-                          for deflate, or the decoding state for inflate */
-  unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */
-  unsigned long reserved; /* reserved for future use */
-} z_stream;
-
-IMPORT int deflateInit_(z_stream *strm, int level, const char *version,
-                        int stream_size);
-IMPORT int inflateInit_(z_stream *strm, const char *version, int stream_size);
-
-#define deflateInit(strm, level)                                               \
-  deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#define inflateInit(strm)                                                      \
-  inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
-
-IMPORT int deflate(z_stream *strm, int flush);
-IMPORT int inflate(z_stream *strm, int flush);
-
-IMPORT int deflateEnd(z_stream *strm);
-IMPORT int inflateEnd(z_stream *strm);
-
+    __attribute__((import_module("wasmedge_zlib")))
 #endif
-
-// ----------------------------------------------------------
-
-static constexpr size_t DataSize = 1 * 1024 * 1024;
-
-constexpr auto RandChar = []() -> char {
-  constexpr char Charset[] = "0123456789"
-                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                             "abcdefghijklmnopqrstuvwxyz";
-  constexpr size_t MaxIndex = (sizeof(Charset) - 1);
-  return Charset[rand() % MaxIndex];
-};
-
-void *CustomMalloc(void *Opaque, unsigned int Items, unsigned int Size) {
-
-  auto Add = malloc(Items * Size);
-  std::cout << "zalloc : " << Add << " = " << Items * Size << std::endl;
-  return Add;
+    int32_t uncompress(uint8_t* dest, size_t* destLen, const uint8_t* source, size_t sourceLen);
 }
 
-void CustomFree(void *Opaque, void *Address) {
-  std::cout << "zfree : " << Address << std::endl;
-
-  free(Address);
-}
-
-int InitDeflateZStream(z_stream &Strm, int Level) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
-
-  int Ret = deflateInit(&Strm, Level);
+// WIT interface implementation functions
path: examples/plugin/wasmedge-zlib/main.cpp
user: login: hydai
body: Yup, I think so.
Otherwise, it's the same as the previous solution.
created_at: 2025-05-27T07:44:21Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,5 @@
+package example:zlib@0.1.0;
+
+world zlib-component {
+    export compressor;
+}
path: examples/plugin/wasmedge-zlib/wit/world.wit
user: login: hydai
body: EOF
created_at: 2025-05-31T18:54:37Z
author_association: MEMBER
diff_hunk: @@ -1,238 +1,346 @@
 #include <algorithm>
-#include <cstddef>
-#include <cstdint>
 #include <cstdlib>
-#include <cstring>
+#include <ctime>
 #include <iostream>
-#include <iterator>
-#include <random>
-#include <type_traits>
 #include <vector>
 
-// ----------------------------------------------------------
-// TODO: LOOK FOR A .WIT REPLACEMENT
-
-#ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#define PRESERVE EMSCRIPTEN_KEEPALIVE
-#define IMPORT __attribute__((import_module("wasmedge_zlib"))) extern "C"
-#else
+// For native use the zlib library
+#ifndef __EMSCRIPTEN__
 #include <zlib.h>
-#define PRESERVE
-#define IMPORT extern "C"
 #endif
 
+// Include the wit-bindgen generated header only for Emscripten(wasm) builds.
 #ifdef __EMSCRIPTEN__
+#include "bindings/zlib_component.h"
+#endif
 
-#define ZLIB_VERSION "1.2.11"
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_STREAM_ERROR (-2)
-#define Z_FINISH 4
-#define Z_NULL NULL
-
-typedef void *(*alloc_func)(void *opaque, unsigned int items,
-                            unsigned int size);
-typedef void (*free_func)(void *opaque, void *address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-  unsigned char *next_in; /* next input byte */
-  uint32_t avail_in;      /* number of bytes available at next_in */
-  unsigned long total_in; /* total number of input bytes read so far */
-
-  unsigned char *next_out; /* next output byte will go here */
-  uint32_t avail_out;      /* remaining free space at next_out */
-  unsigned long total_out; /* total number of bytes output so far */
-
-  char *msg;                    /* last error message, NULL if no error */
-  struct internal_state *state; /* not visible by applications */
-
-  alloc_func zalloc; /* used to allocate the internal state */
-  free_func zfree;   /* used to free the internal state */
-  void *opaque;      /* private data object passed to zalloc and zfree */
-
-  int data_type;       /* best guess about the data type: binary or text
-                          for deflate, or the decoding state for inflate */
-  unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */
-  unsigned long reserved; /* reserved for future use */
-} z_stream;
-
-IMPORT int deflateInit_(z_stream *strm, int level, const char *version,
-                        int stream_size);
-IMPORT int inflateInit_(z_stream *strm, const char *version, int stream_size);
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ZLIB Function Implementations
+// These are used by the test() function directly.
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+extern "C" {
+#ifdef __EMSCRIPTEN__
+// Wasm imports for Emscripten builds
+__attribute__((import_module("wasmedge_zlib"))) int32_t compress(
+    uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen);
 
-#define deflateInit(strm, level)                                               \
-  deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#define inflateInit(strm)                                                      \
-  inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+__attribute__((import_module("wasmedge_zlib"))) int32_t uncompress(
+    uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen);
 
-IMPORT int deflate(z_stream *strm, int flush);
-IMPORT int inflate(z_stream *strm, int flush);
+// Define our internal compress/uncompress to call the Wasm imports
+int32_t zlib_custom_compress(uint8_t *dest, size_t *destLen,
+                             const uint8_t *source, size_t sourceLen) {
+  return compress(dest, destLen, source, sourceLen);
+}
+int32_t zlib_custom_uncompress(uint8_t *dest, size_t *destLen,
+                               const uint8_t *source, size_t sourceLen) {
+  return uncompress(dest, destLen, source, sourceLen);
+}
 
-IMPORT int deflateEnd(z_stream *strm);
-IMPORT int inflateEnd(z_stream *strm);
+#else
+// Native zlib wrapper functions
+int32_t zlib_custom_compress(uint8_t *dest, size_t *destLen,
+                             const uint8_t *source, size_t sourceLen) {
+  uLongf z_destLen = *destLen;
+  int ret = ::compress(dest, &z_destLen, source, (uLong)sourceLen);
+  if (ret == Z_OK) {
+    *destLen = (size_t)z_destLen;
+    return 0;
+  }
+  return ret;
+}
 
+int32_t zlib_custom_uncompress(uint8_t *dest, size_t *destLen,
+                               const uint8_t *source, size_t sourceLen) {
+  uLongf z_destLen = *destLen;
+  int ret = ::uncompress(dest, &z_destLen, source, (uLong)sourceLen);
+  if (ret == Z_OK) {
+    *destLen = (size_t)z_destLen;
+    return 0;
+  }
+  return ret;
+}
 #endif
+} // extern "C"
 
-// ----------------------------------------------------------
-
-static constexpr size_t DataSize = 1 * 1024 * 1024;
-
-constexpr auto RandChar = []() -> char {
-  constexpr char Charset[] = "0123456789"
-                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                             "abcdefghijklmnopqrstuvwxyz";
-  constexpr size_t MaxIndex = (sizeof(Charset) - 1);
-  return Charset[rand() % MaxIndex];
-};
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// WIT-bindgen C ABI Layer Implementation
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#ifdef __EMSCRIPTEN__
 
-void *CustomMalloc(void *Opaque, unsigned int Items, unsigned int Size) {
+static std::string format_error_helper(const char *prefix, int32_t code) {
+  return std::string(prefix) + std::to_string(code);
+}
 
-  auto Add = malloc(Items * Size);
-  std::cout << "zalloc : " << Add << " = " << Items * Size << std::endl;
-  return Add;
+extern "C" {
+
+// canonical_abi_realloc and canonical_abi_free are required by wit-bindgen
+// generated code.
+__attribute__((export_name("canonical_abi_realloc"))) void *
+canonical_abi_realloc(void *old_ptr, size_t old_size, size_t align,
+                      size_t new_size) {
+  (void)old_size;
+  (void)align;
+  if (new_size == 0) {
+    if (old_ptr) {
+      free(old_ptr);
+    }
+    return nullptr;
+  }
+  void *new_ptr = realloc(old_ptr, new_size);
+  if (new_ptr == nullptr && new_size > 0) {
+    fprintf(stderr,
+            "FATAL: canonical_abi_realloc failed to allocate %zu bytes.\n",
+            new_size);
+  }
+  return new_ptr;
 }
 
-void CustomFree(void *Opaque, void *Address) {
-  std::cout << "zfree : " << Address << std::endl;
+__attribute__((export_name("canonical_abi_free"))) void
+canonical_abi_free(void *ptr, size_t size, size_t align) {
+  (void)size;
+  (void)align;
+  if (ptr) {
+    free(ptr);
+  }
+}
 
-  free(Address);
+// Helper function to convert std::vector<uint8_t> to zlib_component_list_u8_t
+static void vec_to_list_u8(const std::vector<uint8_t> &vec,
+                           zlib_component_list_u8_t *list) {
+  if (vec.empty()) {
+    list->ptr = nullptr;
+    list->len = 0;
+    return;
+  }
+  list->ptr =
+      static_cast<uint8_t *>(canonical_abi_realloc(nullptr, 0, 1, vec.size()));
+  if (list->ptr) {
+    memcpy(list->ptr, vec.data(), vec.size());
+    list->len = vec.size();
+  } else {
+    list->len = 0; // Allocation failed
+    fprintf(stderr, "ABI Layer Error: Memory allocation failed for list_u8_t "
+                    "conversion.\n");
+  }
 }
 
-int InitDeflateZStream(z_stream &Strm, int Level) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
+// Helper function to convert std::string to zlib_component_string_t
+static void str_to_component_string(const std::string &str,
+                                    zlib_component_string_t *comp_str) {
+  if (str.empty()) {
+    comp_str->ptr = nullptr;
+    comp_str->len = 0;
+    return;
+  }
+  comp_str->ptr = static_cast<uint8_t *>(
+      canonical_abi_realloc(nullptr, 0, 1, str.length()));
+  if (comp_str->ptr) {
+    memcpy(comp_str->ptr, str.data(), str.length());
+    comp_str->len = str.length();
+  } else {
+    comp_str->len = 0; // Allocation failed
+    fprintf(
+        stderr,
+        "ABI Layer Error: Memory allocation failed for string conversion.\n");
+  }
+}
 
-  int Ret = deflateInit(&Strm, Level);
+bool exports_example_zlib_compressor_deflate(zlib_component_list_u8_t *input,
+                                             zlib_component_list_u8_t *ret_ok,
+                                             zlib_component_string_t *ret_err) {
+  std::vector<uint8_t> source_data;
+  if (input->len > 0) {
+    if (input->ptr == nullptr) {
+      std::string err_msg =
+          "Invalid input to deflate: non-zero length with null pointer.";
+      str_to_component_string(err_msg, ret_err);
+      ret_ok->ptr = nullptr;
+      ret_ok->len = 0;
+      return false;
+    }
+    source_data.assign(input->ptr, input->ptr + input->len);
+  }
 
-  if (Ret != Z_OK) {
-    std::cerr << "'deflateInit' failed!" << std::endl;
-    std::terminate();
+  if (source_data.empty()) {
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
   }
 
-  return Ret;
-}
+  size_t dest_len_estimate = source_data.size() * 2;
+  if (dest_len_estimate < 128)
+    dest_len_estimate = 128;
 
-int InitInflateZStream(z_stream &Strm) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
+  std::vector<uint8_t> compressed_data(dest_len_estimate);
+  size_t actual_dest_len = dest_len_estimate;
 
-  int Ret = inflateInit(&Strm);
+  int32_t result_code =
+      zlib_custom_compress(compressed_data.data(), &actual_dest_len,
+                           source_data.data(), source_data.size());
 
-  if (Ret != Z_OK) {
-    std::cerr << "'inflateInit' failed!" << std::endl;
-    std::terminate();
+  if (result_code == 0) { // Success
+    compressed_data.resize(actual_dest_len);
+    vec_to_list_u8(compressed_data, ret_ok);
+    if (actual_dest_len > 0 && ret_ok->ptr == nullptr && ret_ok->len == 0) {
+      str_to_component_string("Memory allocation failed for deflate Ok value.",
+                              ret_err);
+      return false;
+    }
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  } else {
+    str_to_component_string(
+        format_error_helper("Compression failed with error code: ",
+                            result_code),
+        ret_err);
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    return false;
   }
-
-  return Ret;
 }
 
-template <typename T>
-std::vector<unsigned char> Deflate(const std::vector<T> &Source,
-                                   int Level = -1) {
-
-  int Ret;
-  z_stream Strm;
-  Ret = InitDeflateZStream(Strm, Level);
-  const std::size_t SrcSize = Source.size() * sizeof(T);
-  std::size_t OutBufferSize = SrcSize / 3 + 16;
-  std::vector<unsigned char> OutBuffer(OutBufferSize, {});
-
-  Strm.avail_in = SrcSize;
-  Strm.next_in = reinterpret_cast<unsigned char *>(
-      const_cast<std::remove_const_t<T> *>(Source.data()));
-  Strm.avail_out = OutBuffer.size();
-  Strm.next_out = OutBuffer.data();
-
-  do {
-
-    if (Strm.avail_out == 0) {
-      const std::size_t ExtensionSize = SrcSize / 3 + 16;
-      Strm.avail_out = ExtensionSize;
-      OutBuffer.resize(OutBufferSize + ExtensionSize, {});
-      Strm.next_out = std::next(OutBuffer.data(), OutBufferSize);
-      OutBufferSize += ExtensionSize;
+bool exports_example_zlib_compressor_inflate(zlib_component_list_u8_t *input,
+                                             zlib_component_list_u8_t *ret_ok,
+                                             zlib_component_string_t *ret_err) {
+  std::vector<uint8_t> source_data;
+  if (input->len > 0) {
+    if (input->ptr == nullptr) {
+      std::string err_msg =
+          "Invalid input to inflate: non-zero length with null pointer.";
+      str_to_component_string(err_msg, ret_err);
+      ret_ok->ptr = nullptr;
+      ret_ok->len = 0;
+      return false;
     }
+    source_data.assign(input->ptr, input->ptr + input->len);
+  }
 
-    Ret = deflate(&Strm, Z_FINISH);
+  if (source_data.empty()) {
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  }
 
-    if (Ret == Z_STREAM_ERROR) {
-      std::cerr << "Zlib Stream Error!" << std::endl;
-      std::terminate();
-    }
-  } while (Ret != Z_STREAM_END);
+  size_t dest_len_estimate = source_data.size() * 4;
+  if (dest_len_estimate < 1024)
+    dest_len_estimate = 1024;
+  if (source_data.size() > (512 * 1024) &&
+      dest_len_estimate < source_data.size() * 8) {
+    dest_len_estimate = source_data.size() * 8;
+  }
 
-  deflateEnd(&Strm);
-  OutBuffer.resize(OutBufferSize - Strm.avail_out);
+  std::vector<uint8_t> decompressed_data(dest_len_estimate);
+  size_t actual_dest_len = dest_len_estimate;
 
-  return OutBuffer;
-}
+  int32_t result_code =
+      zlib_custom_uncompress(decompressed_data.data(), &actual_dest_len,
+                             source_data.data(), source_data.size());
 
-template <typename T>
-std::vector<T> Inflate(const std::vector<unsigned char> &Source) {
-
-  int Ret;
-  z_stream Strm;
-  Ret = InitInflateZStream(Strm);
-  const std::size_t SrcSize = Source.size();
-  std::size_t OutBufferSize = SrcSize / 3 + 16;
-  std::vector<unsigned char> OutBuffer(OutBufferSize, {});
-
-  Strm.avail_in = SrcSize;
-  Strm.next_in = const_cast<unsigned char *>(Source.data());
-  Strm.avail_out = OutBuffer.size();
-  Strm.next_out = OutBuffer.data();
-
-  do {
-
-    if (Strm.avail_out == 0) {
-      const std::size_t ExtensionSize = SrcSize / 3 + 16;
-      Strm.avail_out = ExtensionSize;
-      OutBuffer.resize(OutBufferSize + ExtensionSize, {});
-      Strm.next_out = std::next(OutBuffer.data(), OutBufferSize);
-      OutBufferSize += ExtensionSize;
+  if (result_code == -5 /* Z_BUF_ERROR */ &&
+      actual_dest_len == dest_len_estimate) {
+    size_t larger_dest_len_estimate = dest_len_estimate;
+    if (source_data.size() * 10 > larger_dest_len_estimate) {
+      larger_dest_len_estimate = source_data.size() * 10;
+    } else {
+      larger_dest_len_estimate *= 2;
     }
-
-    Ret = inflate(&Strm, Z_FINISH);
-
-    if (Ret == Z_STREAM_ERROR) {
-      std::cerr << "Zlib Stream Error!" << std::endl;
-      std::terminate();
+    const size_t MAX_DECOMPRESSION_BUFFER = 256 * 1024 * 1024;
+    if (larger_dest_len_estimate > MAX_DECOMPRESSION_BUFFER) {
+      larger_dest_len_estimate = MAX_DECOMPRESSION_BUFFER;
     }
-  } while (Ret != Z_STREAM_END);
 
-  inflateEnd(&Strm);
-  OutBufferSize -= Strm.avail_out;
-
-  std::vector<T> RetBuffer(reinterpret_cast<T *>(OutBuffer.data()),
-                           std::next(reinterpret_cast<T *>(OutBuffer.data()),
-                                     (OutBufferSize / sizeof(T))));
+    if (larger_dest_len_estimate > dest_len_estimate) {
+      fprintf(stderr,
+              "Decompression: Z_BUF_ERROR, retrying with larger buffer: %zu "
+              "bytes (previous: %zu)\n",
+              larger_dest_len_estimate, dest_len_estimate);
+      decompressed_data.resize(larger_dest_len_estimate);
+      actual_dest_len = larger_dest_len_estimate;
+      result_code =
+          zlib_custom_uncompress(decompressed_data.data(), &actual_dest_len,
+                                 source_data.data(), source_data.size());
+    }
+  }
 
-  return RetBuffer;
+  if (result_code == 0) { // Success
+    decompressed_data.resize(actual_dest_len);
+    vec_to_list_u8(decompressed_data, ret_ok);
+    if (actual_dest_len > 0 && ret_ok->ptr == nullptr && ret_ok->len == 0) {
+      str_to_component_string("Memory allocation failed for inflate Ok value.",
+                              ret_err);
+      return false;
+    }
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  } else {
+    str_to_component_string(
+        format_error_helper("Decompression failed with error code: ",
+                            result_code),
+        ret_err);
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    return false;
+  }
 }
 
+} // extern "C"
+#endif // __EMSCRIPTEN__
+
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Test function and main
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 int test() {
-  std::vector<char> Data(DataSize, {});
-  std::generate_n(std::begin(Data), DataSize, RandChar);
+  const size_t DataSize = 1 * 1024 * 1024;
+  std::vector<uint8_t> Data(DataSize);
+  std::generate(Data.begin(), Data.end(), []() -> uint8_t {
+    constexpr char Charset[] = "0123456789"
+                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                               "abcdefghijklmnopqrstuvwxyz";
+    constexpr size_t MaxIndex = (sizeof(Charset) - 1);
+    return static_cast<uint8_t>(Charset[rand() % MaxIndex]);
+  });
 
   std::cout << "Compressing Buffer of size : " << DataSize << "B" << std::endl;
-  const auto CompressedBuffer = Deflate(Data, 6);
-
-  std::cout << "Decompressing Buffer of size : " << CompressedBuffer.size()
-            << "B" << std::endl;
-  const auto DecompressedBuffer = Inflate<char>(CompressedBuffer);
 
-  auto CompareResult = Data == DecompressedBuffer;
-  std::cout << (CompareResult ? "Success" : "Fail") << std::endl;
+  // Test compression
+  size_t compressedSize = DataSize * 2;
+  std::vector<uint8_t> compressed(compressedSize);
+  // Use zlib_custom_compress
+  int32_t result = zlib_custom_compress(compressed.data(), &compressedSize,
+                                        Data.data(), Data.size());
+  if (result != 0) {
+    std::cerr << "Compression failed with error code: " << result << std::endl;
+    return 1;
+  }
+  compressed.resize(compressedSize);
+
+  std::cout << "Decompressing Buffer of size : " << compressed.size() << "B"
+            << std::endl;
+
+  // Test decompression
+  size_t decompressedSize = DataSize;
+  std::vector<uint8_t> decompressed(decompressedSize);
+
+  // Use zlib_custom_uncompress
+  result = zlib_custom_uncompress(decompressed.data(), &decompressedSize,
+                                  compressed.data(), compressed.size());
+  if (result != 0) {
+    std::cerr << "Decompression failed with error code: " << result
+              << std::endl;
+    return 1;
+  }
+  decompressed.resize(decompressedSize);
 
-  return CompareResult;
+  bool const success = (Data == decompressed);
+  std::cout << (success ? "Success" : "Fail") << std::endl;
+  return success ? 0 : 1;
 }
 
-int main() {
-  test();
-  return 0;
-}
+int main() { return test(); }
path: examples/plugin/wasmedge-zlib/main.cpp
user: login: hydai
body: EOF
created_at: 2025-05-31T18:54:45Z
author_association: MEMBER
diff_hunk: @@ -1,238 +1,346 @@
 #include <algorithm>
-#include <cstddef>
-#include <cstdint>
 #include <cstdlib>
-#include <cstring>
+#include <ctime>
 #include <iostream>
-#include <iterator>
-#include <random>
-#include <type_traits>
 #include <vector>
 
-// ----------------------------------------------------------
-// TODO: LOOK FOR A .WIT REPLACEMENT
-
-#ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#define PRESERVE EMSCRIPTEN_KEEPALIVE
-#define IMPORT __attribute__((import_module("wasmedge_zlib"))) extern "C"
-#else
+// For native use the zlib library
+#ifndef __EMSCRIPTEN__
 #include <zlib.h>
-#define PRESERVE
-#define IMPORT extern "C"
 #endif
 
+// Include the wit-bindgen generated header only for Emscripten(wasm) builds.
 #ifdef __EMSCRIPTEN__
+#include "bindings/zlib_component.h"
+#endif
 
-#define ZLIB_VERSION "1.2.11"
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_STREAM_ERROR (-2)
-#define Z_FINISH 4
-#define Z_NULL NULL
-
-typedef void *(*alloc_func)(void *opaque, unsigned int items,
-                            unsigned int size);
-typedef void (*free_func)(void *opaque, void *address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-  unsigned char *next_in; /* next input byte */
-  uint32_t avail_in;      /* number of bytes available at next_in */
-  unsigned long total_in; /* total number of input bytes read so far */
-
-  unsigned char *next_out; /* next output byte will go here */
-  uint32_t avail_out;      /* remaining free space at next_out */
-  unsigned long total_out; /* total number of bytes output so far */
-
-  char *msg;                    /* last error message, NULL if no error */
-  struct internal_state *state; /* not visible by applications */
-
-  alloc_func zalloc; /* used to allocate the internal state */
-  free_func zfree;   /* used to free the internal state */
-  void *opaque;      /* private data object passed to zalloc and zfree */
-
-  int data_type;       /* best guess about the data type: binary or text
-                          for deflate, or the decoding state for inflate */
-  unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */
-  unsigned long reserved; /* reserved for future use */
-} z_stream;
-
-IMPORT int deflateInit_(z_stream *strm, int level, const char *version,
-                        int stream_size);
-IMPORT int inflateInit_(z_stream *strm, const char *version, int stream_size);
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ZLIB Function Implementations
+// These are used by the test() function directly.
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+extern "C" {
+#ifdef __EMSCRIPTEN__
+// Wasm imports for Emscripten builds
+__attribute__((import_module("wasmedge_zlib"))) int32_t compress(
+    uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen);
 
-#define deflateInit(strm, level)                                               \
-  deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#define inflateInit(strm)                                                      \
-  inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+__attribute__((import_module("wasmedge_zlib"))) int32_t uncompress(
+    uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen);
 
-IMPORT int deflate(z_stream *strm, int flush);
-IMPORT int inflate(z_stream *strm, int flush);
+// Define our internal compress/uncompress to call the Wasm imports
+int32_t zlib_custom_compress(uint8_t *dest, size_t *destLen,
+                             const uint8_t *source, size_t sourceLen) {
+  return compress(dest, destLen, source, sourceLen);
+}
+int32_t zlib_custom_uncompress(uint8_t *dest, size_t *destLen,
+                               const uint8_t *source, size_t sourceLen) {
+  return uncompress(dest, destLen, source, sourceLen);
+}
 
-IMPORT int deflateEnd(z_stream *strm);
-IMPORT int inflateEnd(z_stream *strm);
+#else
+// Native zlib wrapper functions
+int32_t zlib_custom_compress(uint8_t *dest, size_t *destLen,
+                             const uint8_t *source, size_t sourceLen) {
+  uLongf z_destLen = *destLen;
+  int ret = ::compress(dest, &z_destLen, source, (uLong)sourceLen);
+  if (ret == Z_OK) {
+    *destLen = (size_t)z_destLen;
+    return 0;
+  }
+  return ret;
+}
 
+int32_t zlib_custom_uncompress(uint8_t *dest, size_t *destLen,
+                               const uint8_t *source, size_t sourceLen) {
+  uLongf z_destLen = *destLen;
+  int ret = ::uncompress(dest, &z_destLen, source, (uLong)sourceLen);
+  if (ret == Z_OK) {
+    *destLen = (size_t)z_destLen;
+    return 0;
+  }
+  return ret;
+}
 #endif
+} // extern "C"
 
-// ----------------------------------------------------------
-
-static constexpr size_t DataSize = 1 * 1024 * 1024;
-
-constexpr auto RandChar = []() -> char {
-  constexpr char Charset[] = "0123456789"
-                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                             "abcdefghijklmnopqrstuvwxyz";
-  constexpr size_t MaxIndex = (sizeof(Charset) - 1);
-  return Charset[rand() % MaxIndex];
-};
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// WIT-bindgen C ABI Layer Implementation
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#ifdef __EMSCRIPTEN__
 
-void *CustomMalloc(void *Opaque, unsigned int Items, unsigned int Size) {
+static std::string format_error_helper(const char *prefix, int32_t code) {
+  return std::string(prefix) + std::to_string(code);
+}
 
-  auto Add = malloc(Items * Size);
-  std::cout << "zalloc : " << Add << " = " << Items * Size << std::endl;
-  return Add;
+extern "C" {
+
+// canonical_abi_realloc and canonical_abi_free are required by wit-bindgen
+// generated code.
+__attribute__((export_name("canonical_abi_realloc"))) void *
+canonical_abi_realloc(void *old_ptr, size_t old_size, size_t align,
+                      size_t new_size) {
+  (void)old_size;
+  (void)align;
+  if (new_size == 0) {
+    if (old_ptr) {
+      free(old_ptr);
+    }
+    return nullptr;
+  }
+  void *new_ptr = realloc(old_ptr, new_size);
+  if (new_ptr == nullptr && new_size > 0) {
+    fprintf(stderr,
+            "FATAL: canonical_abi_realloc failed to allocate %zu bytes.\n",
+            new_size);
+  }
+  return new_ptr;
 }
 
-void CustomFree(void *Opaque, void *Address) {
-  std::cout << "zfree : " << Address << std::endl;
+__attribute__((export_name("canonical_abi_free"))) void
+canonical_abi_free(void *ptr, size_t size, size_t align) {
+  (void)size;
+  (void)align;
+  if (ptr) {
+    free(ptr);
+  }
+}
 
-  free(Address);
+// Helper function to convert std::vector<uint8_t> to zlib_component_list_u8_t
+static void vec_to_list_u8(const std::vector<uint8_t> &vec,
+                           zlib_component_list_u8_t *list) {
+  if (vec.empty()) {
+    list->ptr = nullptr;
+    list->len = 0;
+    return;
+  }
+  list->ptr =
+      static_cast<uint8_t *>(canonical_abi_realloc(nullptr, 0, 1, vec.size()));
+  if (list->ptr) {
+    memcpy(list->ptr, vec.data(), vec.size());
+    list->len = vec.size();
+  } else {
+    list->len = 0; // Allocation failed
+    fprintf(stderr, "ABI Layer Error: Memory allocation failed for list_u8_t "
+                    "conversion.\n");
+  }
 }
 
-int InitDeflateZStream(z_stream &Strm, int Level) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
+// Helper function to convert std::string to zlib_component_string_t
+static void str_to_component_string(const std::string &str,
+                                    zlib_component_string_t *comp_str) {
+  if (str.empty()) {
+    comp_str->ptr = nullptr;
+    comp_str->len = 0;
+    return;
+  }
+  comp_str->ptr = static_cast<uint8_t *>(
+      canonical_abi_realloc(nullptr, 0, 1, str.length()));
+  if (comp_str->ptr) {
+    memcpy(comp_str->ptr, str.data(), str.length());
+    comp_str->len = str.length();
+  } else {
+    comp_str->len = 0; // Allocation failed
+    fprintf(
+        stderr,
+        "ABI Layer Error: Memory allocation failed for string conversion.\n");
+  }
+}
 
-  int Ret = deflateInit(&Strm, Level);
+bool exports_example_zlib_compressor_deflate(zlib_component_list_u8_t *input,
+                                             zlib_component_list_u8_t *ret_ok,
+                                             zlib_component_string_t *ret_err) {
+  std::vector<uint8_t> source_data;
+  if (input->len > 0) {
+    if (input->ptr == nullptr) {
+      std::string err_msg =
+          "Invalid input to deflate: non-zero length with null pointer.";
+      str_to_component_string(err_msg, ret_err);
+      ret_ok->ptr = nullptr;
+      ret_ok->len = 0;
+      return false;
+    }
+    source_data.assign(input->ptr, input->ptr + input->len);
+  }
 
-  if (Ret != Z_OK) {
-    std::cerr << "'deflateInit' failed!" << std::endl;
-    std::terminate();
+  if (source_data.empty()) {
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
   }
 
-  return Ret;
-}
+  size_t dest_len_estimate = source_data.size() * 2;
+  if (dest_len_estimate < 128)
+    dest_len_estimate = 128;
 
-int InitInflateZStream(z_stream &Strm) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
+  std::vector<uint8_t> compressed_data(dest_len_estimate);
+  size_t actual_dest_len = dest_len_estimate;
 
-  int Ret = inflateInit(&Strm);
+  int32_t result_code =
+      zlib_custom_compress(compressed_data.data(), &actual_dest_len,
+                           source_data.data(), source_data.size());
 
-  if (Ret != Z_OK) {
-    std::cerr << "'inflateInit' failed!" << std::endl;
-    std::terminate();
+  if (result_code == 0) { // Success
+    compressed_data.resize(actual_dest_len);
+    vec_to_list_u8(compressed_data, ret_ok);
+    if (actual_dest_len > 0 && ret_ok->ptr == nullptr && ret_ok->len == 0) {
+      str_to_component_string("Memory allocation failed for deflate Ok value.",
+                              ret_err);
+      return false;
+    }
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  } else {
+    str_to_component_string(
+        format_error_helper("Compression failed with error code: ",
+                            result_code),
+        ret_err);
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    return false;
   }
-
-  return Ret;
 }
 
-template <typename T>
-std::vector<unsigned char> Deflate(const std::vector<T> &Source,
-                                   int Level = -1) {
-
-  int Ret;
-  z_stream Strm;
-  Ret = InitDeflateZStream(Strm, Level);
-  const std::size_t SrcSize = Source.size() * sizeof(T);
-  std::size_t OutBufferSize = SrcSize / 3 + 16;
-  std::vector<unsigned char> OutBuffer(OutBufferSize, {});
-
-  Strm.avail_in = SrcSize;
-  Strm.next_in = reinterpret_cast<unsigned char *>(
-      const_cast<std::remove_const_t<T> *>(Source.data()));
-  Strm.avail_out = OutBuffer.size();
-  Strm.next_out = OutBuffer.data();
-
-  do {
-
-    if (Strm.avail_out == 0) {
-      const std::size_t ExtensionSize = SrcSize / 3 + 16;
-      Strm.avail_out = ExtensionSize;
-      OutBuffer.resize(OutBufferSize + ExtensionSize, {});
-      Strm.next_out = std::next(OutBuffer.data(), OutBufferSize);
-      OutBufferSize += ExtensionSize;
+bool exports_example_zlib_compressor_inflate(zlib_component_list_u8_t *input,
+                                             zlib_component_list_u8_t *ret_ok,
+                                             zlib_component_string_t *ret_err) {
+  std::vector<uint8_t> source_data;
+  if (input->len > 0) {
+    if (input->ptr == nullptr) {
+      std::string err_msg =
+          "Invalid input to inflate: non-zero length with null pointer.";
+      str_to_component_string(err_msg, ret_err);
+      ret_ok->ptr = nullptr;
+      ret_ok->len = 0;
+      return false;
     }
+    source_data.assign(input->ptr, input->ptr + input->len);
+  }
 
-    Ret = deflate(&Strm, Z_FINISH);
+  if (source_data.empty()) {
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  }
 
-    if (Ret == Z_STREAM_ERROR) {
-      std::cerr << "Zlib Stream Error!" << std::endl;
-      std::terminate();
-    }
-  } while (Ret != Z_STREAM_END);
+  size_t dest_len_estimate = source_data.size() * 4;
+  if (dest_len_estimate < 1024)
+    dest_len_estimate = 1024;
+  if (source_data.size() > (512 * 1024) &&
+      dest_len_estimate < source_data.size() * 8) {
+    dest_len_estimate = source_data.size() * 8;
+  }
 
-  deflateEnd(&Strm);
-  OutBuffer.resize(OutBufferSize - Strm.avail_out);
+  std::vector<uint8_t> decompressed_data(dest_len_estimate);
+  size_t actual_dest_len = dest_len_estimate;
 
-  return OutBuffer;
-}
+  int32_t result_code =
+      zlib_custom_uncompress(decompressed_data.data(), &actual_dest_len,
+                             source_data.data(), source_data.size());
 
-template <typename T>
-std::vector<T> Inflate(const std::vector<unsigned char> &Source) {
-
-  int Ret;
-  z_stream Strm;
-  Ret = InitInflateZStream(Strm);
-  const std::size_t SrcSize = Source.size();
-  std::size_t OutBufferSize = SrcSize / 3 + 16;
-  std::vector<unsigned char> OutBuffer(OutBufferSize, {});
-
-  Strm.avail_in = SrcSize;
-  Strm.next_in = const_cast<unsigned char *>(Source.data());
-  Strm.avail_out = OutBuffer.size();
-  Strm.next_out = OutBuffer.data();
-
-  do {
-
-    if (Strm.avail_out == 0) {
-      const std::size_t ExtensionSize = SrcSize / 3 + 16;
-      Strm.avail_out = ExtensionSize;
-      OutBuffer.resize(OutBufferSize + ExtensionSize, {});
-      Strm.next_out = std::next(OutBuffer.data(), OutBufferSize);
-      OutBufferSize += ExtensionSize;
+  if (result_code == -5 /* Z_BUF_ERROR */ &&
+      actual_dest_len == dest_len_estimate) {
+    size_t larger_dest_len_estimate = dest_len_estimate;
+    if (source_data.size() * 10 > larger_dest_len_estimate) {
+      larger_dest_len_estimate = source_data.size() * 10;
+    } else {
+      larger_dest_len_estimate *= 2;
     }
-
-    Ret = inflate(&Strm, Z_FINISH);
-
-    if (Ret == Z_STREAM_ERROR) {
-      std::cerr << "Zlib Stream Error!" << std::endl;
-      std::terminate();
+    const size_t MAX_DECOMPRESSION_BUFFER = 256 * 1024 * 1024;
+    if (larger_dest_len_estimate > MAX_DECOMPRESSION_BUFFER) {
+      larger_dest_len_estimate = MAX_DECOMPRESSION_BUFFER;
     }
-  } while (Ret != Z_STREAM_END);
 
-  inflateEnd(&Strm);
-  OutBufferSize -= Strm.avail_out;
-
-  std::vector<T> RetBuffer(reinterpret_cast<T *>(OutBuffer.data()),
-                           std::next(reinterpret_cast<T *>(OutBuffer.data()),
-                                     (OutBufferSize / sizeof(T))));
+    if (larger_dest_len_estimate > dest_len_estimate) {
+      fprintf(stderr,
+              "Decompression: Z_BUF_ERROR, retrying with larger buffer: %zu "
+              "bytes (previous: %zu)\n",
+              larger_dest_len_estimate, dest_len_estimate);
+      decompressed_data.resize(larger_dest_len_estimate);
+      actual_dest_len = larger_dest_len_estimate;
+      result_code =
+          zlib_custom_uncompress(decompressed_data.data(), &actual_dest_len,
+                                 source_data.data(), source_data.size());
+    }
+  }
 
-  return RetBuffer;
+  if (result_code == 0) { // Success
+    decompressed_data.resize(actual_dest_len);
+    vec_to_list_u8(decompressed_data, ret_ok);
+    if (actual_dest_len > 0 && ret_ok->ptr == nullptr && ret_ok->len == 0) {
+      str_to_component_string("Memory allocation failed for inflate Ok value.",
+                              ret_err);
+      return false;
+    }
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  } else {
+    str_to_component_string(
+        format_error_helper("Decompression failed with error code: ",
+                            result_code),
+        ret_err);
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    return false;
+  }
 }
 
+} // extern "C"
+#endif // __EMSCRIPTEN__
+
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Test function and main
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 int test() {
-  std::vector<char> Data(DataSize, {});
-  std::generate_n(std::begin(Data), DataSize, RandChar);
+  const size_t DataSize = 1 * 1024 * 1024;
+  std::vector<uint8_t> Data(DataSize);
+  std::generate(Data.begin(), Data.end(), []() -> uint8_t {
+    constexpr char Charset[] = "0123456789"
+                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                               "abcdefghijklmnopqrstuvwxyz";
+    constexpr size_t MaxIndex = (sizeof(Charset) - 1);
+    return static_cast<uint8_t>(Charset[rand() % MaxIndex]);
+  });
 
   std::cout << "Compressing Buffer of size : " << DataSize << "B" << std::endl;
-  const auto CompressedBuffer = Deflate(Data, 6);
-
-  std::cout << "Decompressing Buffer of size : " << CompressedBuffer.size()
-            << "B" << std::endl;
-  const auto DecompressedBuffer = Inflate<char>(CompressedBuffer);
 
-  auto CompareResult = Data == DecompressedBuffer;
-  std::cout << (CompareResult ? "Success" : "Fail") << std::endl;
+  // Test compression
+  size_t compressedSize = DataSize * 2;
path: examples/plugin/wasmedge-zlib/main.cpp
user: login: hydai
body: Please follow the WasmEdge Coding Style.
created_at: 2025-05-31T18:55:16Z
author_association: MEMBER
diff_hunk: @@ -36,30 +54,98 @@ cmake --build . -j
 # Compiled Wasmedge is located in ./tools/wasmedge/wasmedge
 ```
 
-## Build and Run the example as a WASM Module
+## Build and Run the example using Make
+
+```bash
+cd ./examples/plugin/wasmedge-zlib/
+make all # Build both native and WebAssembly versions
+make clean # Clean the build directory
+make native # Build the native version
+make wasm # Build WebAssembly version
+make run-native # Run the native version
+make run-wasm # Run the WebAssembly version
+make help # Show all available targets
+```
+
+## Manually Build and Run the example as a WASM Module
+
+#### First generate the bindings
 
 ```bash
 cd ../examples/plugin/wasmedge-zlib/
-mkdir build
-em++ main.cpp -O2 -o build/main.wasm -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0
+mkdir -p bindings
+wit-bindgen c wit --out-dir bindings
+```
+
+#### Sanitize the .c file
+
+```bash
+awk -v sanitize_chars_regex='[:/@#%.]' '
+{
+  line = $0; processed_line = 0;
+  prefix_end_marker = "__export_name__(\"";
+  start_pos = index(line, prefix_end_marker);
+  if (start_pos > 0) {
+    name_start_pos = start_pos + length(prefix_end_marker);
+    name_and_suffix_part = substr(line, name_start_pos);
+    closing_quote_pos_in_suffix = index(name_and_suffix_part, "\"");
+    if (closing_quote_pos_in_suffix > 0) {
+      name_to_sanitize = substr(name_and_suffix_part, 1, closing_quote_pos_in_suffix - 1);
+      prefix = substr(line, 1, name_start_pos - 1);
+      suffix = substr(name_and_suffix_part, closing_quote_pos_in_suffix);
+      sanitized_name = name_to_sanitize;
+      gsub(sanitize_chars_regex, "_", sanitized_name);
+      print prefix sanitized_name suffix;
+      processed_line = 1;
+    }
+  }
+  if (processed_line == 0) print line;
+}' bindings/zlib_component.c > bindings/zlib_component.c.tmp && mv bindings/zlib_component.c.tmp bindings/zlib_component.c
+```
+
+#### Build and Link the wasm
+
+```bash
+mkdir -p build/wasm
+
+# Compile C++ source
+em++ -O2 -std=c++17 -Wall -Wextra \
+  -sWARN_ON_UNDEFINED_SYMBOLS=0 \
+  -Ibindings \
+  -c main.cpp -o build/wasm/main.o
+
+# Compile generated bindings
+emcc -O2 -Wall -Wextra \
+  -sWARN_ON_UNDEFINED_SYMBOLS=0 \
+  -Ibindings \
+  -c bindings/zlib_component.c -o build/wasm/zlib_component_bindings.o
+
+# Link with bindings component_type.o
+em++ -O2 -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0 \
+  build/wasm/main.o \
+  build/wasm/zlib_component_bindings.o \
+  bindings/zlib_component_component_type.o \
+  -o build/wasm/main.wasm
 ```
 
-Then we get `build/main.wasm`.
+Then we get `build/wasm/main.wasm`.
 
 We can run this example with `Wasmedge` with the following command
 
 ```bash
-../../../build/tools/wasmedge/wasmedge build/main.wasm
+../../../build/tools/wasmedge/wasmedge build/wasm/main.wasm # wasmedge built from this repo
+wasmedge build/wasm/main.wasm # wasmedge from path(global)
path: examples/plugin/wasmedge-zlib/README.md
user: login: hydai
body: I don't think we need two lines.
You can just keep `wasmedge` here.
created_at: 2025-05-31T18:56:08Z
author_association: MEMBER
diff_hunk: @@ -36,30 +54,98 @@ cmake --build . -j
 # Compiled Wasmedge is located in ./tools/wasmedge/wasmedge
 ```
 
-## Build and Run the example as a WASM Module
+## Build and Run the example using Make
+
+```bash
+cd ./examples/plugin/wasmedge-zlib/
+make all # Build both native and WebAssembly versions
+make clean # Clean the build directory
+make native # Build the native version
+make wasm # Build WebAssembly version
+make run-native # Run the native version
+make run-wasm # Run the WebAssembly version
+make help # Show all available targets
+```
+
+## Manually Build and Run the example as a WASM Module
+
+#### First generate the bindings
 
 ```bash
 cd ../examples/plugin/wasmedge-zlib/
-mkdir build
-em++ main.cpp -O2 -o build/main.wasm -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0
+mkdir -p bindings
+wit-bindgen c wit --out-dir bindings
+```
+
+#### Sanitize the .c file
+
+```bash
+awk -v sanitize_chars_regex='[:/@#%.]' '
path: examples/plugin/wasmedge-zlib/README.md
user: login: hydai
body: Can you explain the reason for sanitizing the C files? 
Does any WIT-generated file require this step?
created_at: 2025-05-31T18:57:00Z
author_association: MEMBER
diff_hunk: @@ -4,6 +4,24 @@ This is an example to demonstrate how to use the `wasmedge-zlib` plugin of WasmE
 
 ## Prerequisites
 
+You need four main components:
+
+1. Emscripten SDK (for compiling to WebAssembly)
+
+2. WasmEdge Runtime
+
+3. wasmedge-zlib plugin
+
+4. wit-bindgen (for generating bindings on the fly)
path: examples/plugin/wasmedge-zlib/README.md
user: login: hydai
body: Since `wit-bindgen` may change its behavior between versions, please specify the version you used here.
created_at: 2025-05-31T18:58:28Z
author_association: MEMBER
diff_hunk: @@ -1 +1,2 @@
 build/
+bindings/
path: examples/plugin/wasmedge-zlib/.gitignore
user: login: hydai
body: EOF
created_at: 2025-05-31T18:58:46Z
author_association: MEMBER
diff_hunk: @@ -36,30 +54,98 @@ cmake --build . -j
 # Compiled Wasmedge is located in ./tools/wasmedge/wasmedge
 ```
 
-## Build and Run the example as a WASM Module
+## Build and Run the example using Make
+
+```bash
+cd ./examples/plugin/wasmedge-zlib/
+make all # Build both native and WebAssembly versions
+make clean # Clean the build directory
+make native # Build the native version
+make wasm # Build WebAssembly version
+make run-native # Run the native version
+make run-wasm # Run the WebAssembly version
+make help # Show all available targets
+```
+
+## Manually Build and Run the example as a WASM Module
+
+#### First generate the bindings
 
 ```bash
 cd ../examples/plugin/wasmedge-zlib/
-mkdir build
-em++ main.cpp -O2 -o build/main.wasm -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0
+mkdir -p bindings
+wit-bindgen c wit --out-dir bindings
+```
+
+#### Sanitize the .c file
+
+```bash
+awk -v sanitize_chars_regex='[:/@#%.]' '
path: examples/plugin/wasmedge-zlib/README.md
user: login: PhantomInTheWire
body: yes the .c file that wit generates has a lot of  #, @, and . characters in the function signatures and Emscripten doesn't seem to like it
created_at: 2025-05-31T19:19:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -36,30 +54,98 @@ cmake --build . -j
 # Compiled Wasmedge is located in ./tools/wasmedge/wasmedge
 ```
 
-## Build and Run the example as a WASM Module
+## Build and Run the example using Make
+
+```bash
+cd ./examples/plugin/wasmedge-zlib/
+make all # Build both native and WebAssembly versions
+make clean # Clean the build directory
+make native # Build the native version
+make wasm # Build WebAssembly version
+make run-native # Run the native version
+make run-wasm # Run the WebAssembly version
+make help # Show all available targets
+```
+
+## Manually Build and Run the example as a WASM Module
+
+#### First generate the bindings
 
 ```bash
 cd ../examples/plugin/wasmedge-zlib/
-mkdir build
-em++ main.cpp -O2 -o build/main.wasm -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0
+mkdir -p bindings
+wit-bindgen c wit --out-dir bindings
+```
+
+#### Sanitize the .c file
+
+```bash
+awk -v sanitize_chars_regex='[:/@#%.]' '
path: examples/plugin/wasmedge-zlib/README.md
user: login: hydai
body: We should mention this inside the README.
created_at: 2025-05-31T19:20:56Z
author_association: MEMBER
diff_hunk: @@ -36,30 +54,98 @@ cmake --build . -j
 # Compiled Wasmedge is located in ./tools/wasmedge/wasmedge
 ```
 
-## Build and Run the example as a WASM Module
+## Build and Run the example using Make
+
+```bash
+cd ./examples/plugin/wasmedge-zlib/
+make all # Build both native and WebAssembly versions
+make clean # Clean the build directory
+make native # Build the native version
+make wasm # Build WebAssembly version
+make run-native # Run the native version
+make run-wasm # Run the WebAssembly version
+make help # Show all available targets
+```
+
+## Manually Build and Run the example as a WASM Module
+
+#### First generate the bindings
 
 ```bash
 cd ../examples/plugin/wasmedge-zlib/
-mkdir build
-em++ main.cpp -O2 -o build/main.wasm -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0
+mkdir -p bindings
+wit-bindgen c wit --out-dir bindings
+```
+
+#### Sanitize the .c file
+
+```bash
+awk -v sanitize_chars_regex='[:/@#%.]' '
path: examples/plugin/wasmedge-zlib/README.md
user: login: PhantomInTheWire
body: Sounds good I’ll add a note about it
created_at: 2025-05-31T19:33:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,238 +1,346 @@
 #include <algorithm>
-#include <cstddef>
-#include <cstdint>
 #include <cstdlib>
-#include <cstring>
+#include <ctime>
 #include <iostream>
-#include <iterator>
-#include <random>
-#include <type_traits>
 #include <vector>
 
-// ----------------------------------------------------------
-// TODO: LOOK FOR A .WIT REPLACEMENT
-
-#ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#define PRESERVE EMSCRIPTEN_KEEPALIVE
-#define IMPORT __attribute__((import_module("wasmedge_zlib"))) extern "C"
-#else
+// For native use the zlib library
+#ifndef __EMSCRIPTEN__
 #include <zlib.h>
-#define PRESERVE
-#define IMPORT extern "C"
 #endif
 
+// Include the wit-bindgen generated header only for Emscripten(wasm) builds.
 #ifdef __EMSCRIPTEN__
+#include "bindings/zlib_component.h"
+#endif
 
-#define ZLIB_VERSION "1.2.11"
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_STREAM_ERROR (-2)
-#define Z_FINISH 4
-#define Z_NULL NULL
-
-typedef void *(*alloc_func)(void *opaque, unsigned int items,
-                            unsigned int size);
-typedef void (*free_func)(void *opaque, void *address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-  unsigned char *next_in; /* next input byte */
-  uint32_t avail_in;      /* number of bytes available at next_in */
-  unsigned long total_in; /* total number of input bytes read so far */
-
-  unsigned char *next_out; /* next output byte will go here */
-  uint32_t avail_out;      /* remaining free space at next_out */
-  unsigned long total_out; /* total number of bytes output so far */
-
-  char *msg;                    /* last error message, NULL if no error */
-  struct internal_state *state; /* not visible by applications */
-
-  alloc_func zalloc; /* used to allocate the internal state */
-  free_func zfree;   /* used to free the internal state */
-  void *opaque;      /* private data object passed to zalloc and zfree */
-
-  int data_type;       /* best guess about the data type: binary or text
-                          for deflate, or the decoding state for inflate */
-  unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */
-  unsigned long reserved; /* reserved for future use */
-} z_stream;
-
-IMPORT int deflateInit_(z_stream *strm, int level, const char *version,
-                        int stream_size);
-IMPORT int inflateInit_(z_stream *strm, const char *version, int stream_size);
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ZLIB Function Implementations
+// These are used by the test() function directly.
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+extern "C" {
+#ifdef __EMSCRIPTEN__
+// Wasm imports for Emscripten builds
+__attribute__((import_module("wasmedge_zlib"))) int32_t compress(
+    uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen);
 
-#define deflateInit(strm, level)                                               \
-  deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
-#define inflateInit(strm)                                                      \
-  inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+__attribute__((import_module("wasmedge_zlib"))) int32_t uncompress(
+    uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen);
 
-IMPORT int deflate(z_stream *strm, int flush);
-IMPORT int inflate(z_stream *strm, int flush);
+// Define our internal compress/uncompress to call the Wasm imports
+int32_t zlib_custom_compress(uint8_t *dest, size_t *destLen,
+                             const uint8_t *source, size_t sourceLen) {
+  return compress(dest, destLen, source, sourceLen);
+}
+int32_t zlib_custom_uncompress(uint8_t *dest, size_t *destLen,
+                               const uint8_t *source, size_t sourceLen) {
+  return uncompress(dest, destLen, source, sourceLen);
+}
 
-IMPORT int deflateEnd(z_stream *strm);
-IMPORT int inflateEnd(z_stream *strm);
+#else
+// Native zlib wrapper functions
+int32_t zlib_custom_compress(uint8_t *dest, size_t *destLen,
+                             const uint8_t *source, size_t sourceLen) {
+  uLongf z_destLen = *destLen;
+  int ret = ::compress(dest, &z_destLen, source, (uLong)sourceLen);
+  if (ret == Z_OK) {
+    *destLen = (size_t)z_destLen;
+    return 0;
+  }
+  return ret;
+}
 
+int32_t zlib_custom_uncompress(uint8_t *dest, size_t *destLen,
+                               const uint8_t *source, size_t sourceLen) {
+  uLongf z_destLen = *destLen;
+  int ret = ::uncompress(dest, &z_destLen, source, (uLong)sourceLen);
+  if (ret == Z_OK) {
+    *destLen = (size_t)z_destLen;
+    return 0;
+  }
+  return ret;
+}
 #endif
+} // extern "C"
 
-// ----------------------------------------------------------
-
-static constexpr size_t DataSize = 1 * 1024 * 1024;
-
-constexpr auto RandChar = []() -> char {
-  constexpr char Charset[] = "0123456789"
-                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                             "abcdefghijklmnopqrstuvwxyz";
-  constexpr size_t MaxIndex = (sizeof(Charset) - 1);
-  return Charset[rand() % MaxIndex];
-};
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// WIT-bindgen C ABI Layer Implementation
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#ifdef __EMSCRIPTEN__
 
-void *CustomMalloc(void *Opaque, unsigned int Items, unsigned int Size) {
+static std::string format_error_helper(const char *prefix, int32_t code) {
+  return std::string(prefix) + std::to_string(code);
+}
 
-  auto Add = malloc(Items * Size);
-  std::cout << "zalloc : " << Add << " = " << Items * Size << std::endl;
-  return Add;
+extern "C" {
+
+// canonical_abi_realloc and canonical_abi_free are required by wit-bindgen
+// generated code.
+__attribute__((export_name("canonical_abi_realloc"))) void *
+canonical_abi_realloc(void *old_ptr, size_t old_size, size_t align,
+                      size_t new_size) {
+  (void)old_size;
+  (void)align;
+  if (new_size == 0) {
+    if (old_ptr) {
+      free(old_ptr);
+    }
+    return nullptr;
+  }
+  void *new_ptr = realloc(old_ptr, new_size);
+  if (new_ptr == nullptr && new_size > 0) {
+    fprintf(stderr,
+            "FATAL: canonical_abi_realloc failed to allocate %zu bytes.\n",
+            new_size);
+  }
+  return new_ptr;
 }
 
-void CustomFree(void *Opaque, void *Address) {
-  std::cout << "zfree : " << Address << std::endl;
+__attribute__((export_name("canonical_abi_free"))) void
+canonical_abi_free(void *ptr, size_t size, size_t align) {
+  (void)size;
+  (void)align;
+  if (ptr) {
+    free(ptr);
+  }
+}
 
-  free(Address);
+// Helper function to convert std::vector<uint8_t> to zlib_component_list_u8_t
+static void vec_to_list_u8(const std::vector<uint8_t> &vec,
+                           zlib_component_list_u8_t *list) {
+  if (vec.empty()) {
+    list->ptr = nullptr;
+    list->len = 0;
+    return;
+  }
+  list->ptr =
+      static_cast<uint8_t *>(canonical_abi_realloc(nullptr, 0, 1, vec.size()));
+  if (list->ptr) {
+    memcpy(list->ptr, vec.data(), vec.size());
+    list->len = vec.size();
+  } else {
+    list->len = 0; // Allocation failed
+    fprintf(stderr, "ABI Layer Error: Memory allocation failed for list_u8_t "
+                    "conversion.\n");
+  }
 }
 
-int InitDeflateZStream(z_stream &Strm, int Level) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
+// Helper function to convert std::string to zlib_component_string_t
+static void str_to_component_string(const std::string &str,
+                                    zlib_component_string_t *comp_str) {
+  if (str.empty()) {
+    comp_str->ptr = nullptr;
+    comp_str->len = 0;
+    return;
+  }
+  comp_str->ptr = static_cast<uint8_t *>(
+      canonical_abi_realloc(nullptr, 0, 1, str.length()));
+  if (comp_str->ptr) {
+    memcpy(comp_str->ptr, str.data(), str.length());
+    comp_str->len = str.length();
+  } else {
+    comp_str->len = 0; // Allocation failed
+    fprintf(
+        stderr,
+        "ABI Layer Error: Memory allocation failed for string conversion.\n");
+  }
+}
 
-  int Ret = deflateInit(&Strm, Level);
+bool exports_example_zlib_compressor_deflate(zlib_component_list_u8_t *input,
+                                             zlib_component_list_u8_t *ret_ok,
+                                             zlib_component_string_t *ret_err) {
+  std::vector<uint8_t> source_data;
+  if (input->len > 0) {
+    if (input->ptr == nullptr) {
+      std::string err_msg =
+          "Invalid input to deflate: non-zero length with null pointer.";
+      str_to_component_string(err_msg, ret_err);
+      ret_ok->ptr = nullptr;
+      ret_ok->len = 0;
+      return false;
+    }
+    source_data.assign(input->ptr, input->ptr + input->len);
+  }
 
-  if (Ret != Z_OK) {
-    std::cerr << "'deflateInit' failed!" << std::endl;
-    std::terminate();
+  if (source_data.empty()) {
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
   }
 
-  return Ret;
-}
+  size_t dest_len_estimate = source_data.size() * 2;
+  if (dest_len_estimate < 128)
+    dest_len_estimate = 128;
 
-int InitInflateZStream(z_stream &Strm) {
-  Strm.zalloc = CustomMalloc;
-  Strm.zfree = CustomFree;
-  Strm.opaque = Z_NULL;
+  std::vector<uint8_t> compressed_data(dest_len_estimate);
+  size_t actual_dest_len = dest_len_estimate;
 
-  int Ret = inflateInit(&Strm);
+  int32_t result_code =
+      zlib_custom_compress(compressed_data.data(), &actual_dest_len,
+                           source_data.data(), source_data.size());
 
-  if (Ret != Z_OK) {
-    std::cerr << "'inflateInit' failed!" << std::endl;
-    std::terminate();
+  if (result_code == 0) { // Success
+    compressed_data.resize(actual_dest_len);
+    vec_to_list_u8(compressed_data, ret_ok);
+    if (actual_dest_len > 0 && ret_ok->ptr == nullptr && ret_ok->len == 0) {
+      str_to_component_string("Memory allocation failed for deflate Ok value.",
+                              ret_err);
+      return false;
+    }
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  } else {
+    str_to_component_string(
+        format_error_helper("Compression failed with error code: ",
+                            result_code),
+        ret_err);
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    return false;
   }
-
-  return Ret;
 }
 
-template <typename T>
-std::vector<unsigned char> Deflate(const std::vector<T> &Source,
-                                   int Level = -1) {
-
-  int Ret;
-  z_stream Strm;
-  Ret = InitDeflateZStream(Strm, Level);
-  const std::size_t SrcSize = Source.size() * sizeof(T);
-  std::size_t OutBufferSize = SrcSize / 3 + 16;
-  std::vector<unsigned char> OutBuffer(OutBufferSize, {});
-
-  Strm.avail_in = SrcSize;
-  Strm.next_in = reinterpret_cast<unsigned char *>(
-      const_cast<std::remove_const_t<T> *>(Source.data()));
-  Strm.avail_out = OutBuffer.size();
-  Strm.next_out = OutBuffer.data();
-
-  do {
-
-    if (Strm.avail_out == 0) {
-      const std::size_t ExtensionSize = SrcSize / 3 + 16;
-      Strm.avail_out = ExtensionSize;
-      OutBuffer.resize(OutBufferSize + ExtensionSize, {});
-      Strm.next_out = std::next(OutBuffer.data(), OutBufferSize);
-      OutBufferSize += ExtensionSize;
+bool exports_example_zlib_compressor_inflate(zlib_component_list_u8_t *input,
+                                             zlib_component_list_u8_t *ret_ok,
+                                             zlib_component_string_t *ret_err) {
+  std::vector<uint8_t> source_data;
+  if (input->len > 0) {
+    if (input->ptr == nullptr) {
+      std::string err_msg =
+          "Invalid input to inflate: non-zero length with null pointer.";
+      str_to_component_string(err_msg, ret_err);
+      ret_ok->ptr = nullptr;
+      ret_ok->len = 0;
+      return false;
     }
+    source_data.assign(input->ptr, input->ptr + input->len);
+  }
 
-    Ret = deflate(&Strm, Z_FINISH);
+  if (source_data.empty()) {
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  }
 
-    if (Ret == Z_STREAM_ERROR) {
-      std::cerr << "Zlib Stream Error!" << std::endl;
-      std::terminate();
-    }
-  } while (Ret != Z_STREAM_END);
+  size_t dest_len_estimate = source_data.size() * 4;
+  if (dest_len_estimate < 1024)
+    dest_len_estimate = 1024;
+  if (source_data.size() > (512 * 1024) &&
+      dest_len_estimate < source_data.size() * 8) {
+    dest_len_estimate = source_data.size() * 8;
+  }
 
-  deflateEnd(&Strm);
-  OutBuffer.resize(OutBufferSize - Strm.avail_out);
+  std::vector<uint8_t> decompressed_data(dest_len_estimate);
+  size_t actual_dest_len = dest_len_estimate;
 
-  return OutBuffer;
-}
+  int32_t result_code =
+      zlib_custom_uncompress(decompressed_data.data(), &actual_dest_len,
+                             source_data.data(), source_data.size());
 
-template <typename T>
-std::vector<T> Inflate(const std::vector<unsigned char> &Source) {
-
-  int Ret;
-  z_stream Strm;
-  Ret = InitInflateZStream(Strm);
-  const std::size_t SrcSize = Source.size();
-  std::size_t OutBufferSize = SrcSize / 3 + 16;
-  std::vector<unsigned char> OutBuffer(OutBufferSize, {});
-
-  Strm.avail_in = SrcSize;
-  Strm.next_in = const_cast<unsigned char *>(Source.data());
-  Strm.avail_out = OutBuffer.size();
-  Strm.next_out = OutBuffer.data();
-
-  do {
-
-    if (Strm.avail_out == 0) {
-      const std::size_t ExtensionSize = SrcSize / 3 + 16;
-      Strm.avail_out = ExtensionSize;
-      OutBuffer.resize(OutBufferSize + ExtensionSize, {});
-      Strm.next_out = std::next(OutBuffer.data(), OutBufferSize);
-      OutBufferSize += ExtensionSize;
+  if (result_code == -5 /* Z_BUF_ERROR */ &&
+      actual_dest_len == dest_len_estimate) {
+    size_t larger_dest_len_estimate = dest_len_estimate;
+    if (source_data.size() * 10 > larger_dest_len_estimate) {
+      larger_dest_len_estimate = source_data.size() * 10;
+    } else {
+      larger_dest_len_estimate *= 2;
     }
-
-    Ret = inflate(&Strm, Z_FINISH);
-
-    if (Ret == Z_STREAM_ERROR) {
-      std::cerr << "Zlib Stream Error!" << std::endl;
-      std::terminate();
+    const size_t MAX_DECOMPRESSION_BUFFER = 256 * 1024 * 1024;
+    if (larger_dest_len_estimate > MAX_DECOMPRESSION_BUFFER) {
+      larger_dest_len_estimate = MAX_DECOMPRESSION_BUFFER;
     }
-  } while (Ret != Z_STREAM_END);
 
-  inflateEnd(&Strm);
-  OutBufferSize -= Strm.avail_out;
-
-  std::vector<T> RetBuffer(reinterpret_cast<T *>(OutBuffer.data()),
-                           std::next(reinterpret_cast<T *>(OutBuffer.data()),
-                                     (OutBufferSize / sizeof(T))));
+    if (larger_dest_len_estimate > dest_len_estimate) {
+      fprintf(stderr,
+              "Decompression: Z_BUF_ERROR, retrying with larger buffer: %zu "
+              "bytes (previous: %zu)\n",
+              larger_dest_len_estimate, dest_len_estimate);
+      decompressed_data.resize(larger_dest_len_estimate);
+      actual_dest_len = larger_dest_len_estimate;
+      result_code =
+          zlib_custom_uncompress(decompressed_data.data(), &actual_dest_len,
+                                 source_data.data(), source_data.size());
+    }
+  }
 
-  return RetBuffer;
+  if (result_code == 0) { // Success
+    decompressed_data.resize(actual_dest_len);
+    vec_to_list_u8(decompressed_data, ret_ok);
+    if (actual_dest_len > 0 && ret_ok->ptr == nullptr && ret_ok->len == 0) {
+      str_to_component_string("Memory allocation failed for inflate Ok value.",
+                              ret_err);
+      return false;
+    }
+    ret_err->ptr = nullptr;
+    ret_err->len = 0;
+    return true;
+  } else {
+    str_to_component_string(
+        format_error_helper("Decompression failed with error code: ",
+                            result_code),
+        ret_err);
+    ret_ok->ptr = nullptr;
+    ret_ok->len = 0;
+    return false;
+  }
 }
 
+} // extern "C"
+#endif // __EMSCRIPTEN__
+
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Test function and main
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 int test() {
-  std::vector<char> Data(DataSize, {});
-  std::generate_n(std::begin(Data), DataSize, RandChar);
+  const size_t DataSize = 1 * 1024 * 1024;
+  std::vector<uint8_t> Data(DataSize);
+  std::generate(Data.begin(), Data.end(), []() -> uint8_t {
+    constexpr char Charset[] = "0123456789"
+                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                               "abcdefghijklmnopqrstuvwxyz";
+    constexpr size_t MaxIndex = (sizeof(Charset) - 1);
+    return static_cast<uint8_t>(Charset[rand() % MaxIndex]);
+  });
 
   std::cout << "Compressing Buffer of size : " << DataSize << "B" << std::endl;
-  const auto CompressedBuffer = Deflate(Data, 6);
-
-  std::cout << "Decompressing Buffer of size : " << CompressedBuffer.size()
-            << "B" << std::endl;
-  const auto DecompressedBuffer = Inflate<char>(CompressedBuffer);
 
-  auto CompareResult = Data == DecompressedBuffer;
-  std::cout << (CompareResult ? "Success" : "Fail") << std::endl;
+  // Test compression
+  size_t compressedSize = DataSize * 2;
path: examples/plugin/wasmedge-zlib/main.cpp
user: login: PhantomInTheWire
body: I've updated the case styles to follow the WasmEdge Coding Style in all places except a few where doing so would break compatibility. I've added a note at the top of `main.cpp` explaining the exceptions:
```cpp
// NOTE: Some function signatures, structs etc need to be same as the ones in zlib_component.h
// example: `bool exports_example_zlib_compressor_deflate(...)`
// This is to ensure that the C ABI layer can call these functions correctly.
// This is also true for some extern "C" functions.
```
created_at: 2025-05-31T22:01:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -4,6 +4,24 @@ This is an example to demonstrate how to use the `wasmedge-zlib` plugin of WasmE
 
 ## Prerequisites
 
+You need four main components:
+
+1. Emscripten SDK (for compiling to WebAssembly)
+
+2. WasmEdge Runtime
+
+3. wasmedge-zlib plugin
+
+4. wit-bindgen (for generating bindings on the fly)
path: examples/plugin/wasmedge-zlib/README.md
user: login: PhantomInTheWire
body: done.
created_at: 2025-05-31T22:01:55Z
author_association: CONTRIBUTOR

PR comments:
user: login: juntao
created_at: 2025-05-26T15:47:00Z
body: Hello, I am a [code review agent](https://github.com/flows-network/github-pr-review/) on [flows.network](https://flows.network/). Here are my reviews of changed source code files in this PR.

------

## [examples/plugin/wasmedge-zlib/.gitignore](https://github.com/WasmEdge/WasmEdge/blob/6461cd0f709f958a086ec884a352622e064444c7/examples%2Fplugin%2Fwasmedge-zlib%2F.gitignore)

#### Potential issues

1. **Issue**: The patch does not include any modifications to the `build/` directory, which suggests that build configurations or scripts may need updating to support WIT.
   
2. **Issue**: There are no changes in the `bindings/` directory, indicating potential discrepancies in how the example interacts with other language bindings if they rely on the same zlib functionality.

3. **Issue**: The patch does not address any integration tests or examples that might depend on the old implementation, potentially leading to failing tests or outdated documentation.

#### Summary of changes

- • Added `bindings/` directory to the project.
• The patch indicates a structural change, likely to accommodate new bindings or integrations, specifically for WIT (WebAssembly Interface Types).
• No direct code changes are shown; the addition of the directory suggests preparation for integrating zlib with WIT.

## [examples/plugin/wasmedge-zlib/Makefile](https://github.com/WasmEdge/WasmEdge/blob/6461cd0f709f958a086ec884a352622e064444c7/examples%2Fplugin%2Fwasmedge-zlib%2FMakefile)

#### Potential issues

1. **Incorrect Object File for Native Executable**: The rule for building `$(NATIVE_EXE)` depends on `$(BUILD_NATIVE_DIR)/main_native.o`, but the file generated by the corresponding rule is actually `$(BUILD_NATIVE_DIR)/main.o`. This will cause a build failure.

2. **Missing Dependency in WASM Build**: The WASM build rule for `$(WASM_EXE)` should include `$(BINDINGS_C) $(BINDINGS_H)` as dependencies to ensure that changes in WIT bindings trigger a rebuild of the WASM module.

3. **Redundant Compilation Flag `-sWARN_ON_UNDEFINED_SYMBOLS=0`**: This flag is set multiple times in different rules without any condition checking. Consider consolidating it into a single variable or ensuring it's only set where necessary to avoid redundancy and potential confusion.

#### Summary of changes

- - Added comprehensive Makefile to handle build, run, and dependency checks for both native and WASM targets.
- Implemented WIT (WebAssembly Interface Types) binding generation and sanitization processes for the zlib example.
- Included support for building and running WebAssembly modules using Emscripten and WasmEdge, respectively.

## [examples/plugin/wasmedge-zlib/main.cpp](https://github.com/WasmEdge/WasmEdge/blob/6461cd0f709f958a086ec884a352622e064444c7/examples%2Fplugin%2Fwasmedge-zlib%2Fmain.cpp)

#### Potential issues

1. **Memory Leak in `vecToListU8` and `strToComponentString`:** Memory allocated with `canonical_abi_realloc` is not freed if an error occurs (e.g., allocation fails). This results in memory leaks.

2. **Incorrect Error Code Check for Zlib Functions:** The success return code for zlib functions (`zlibCustomCompress` and `zlibCustomUncompress`) is checked against `0`, which is correct, but the failure handling should be more robust by checking specific error codes to provide meaningful error messages or recovery actions.

3. **Potential Buffer Overflow in Decompression Logic:** The logic for increasing the buffer size during decompression (`LargerDestLenEstimate`) can still lead to a situation where `DecompressedData` is not resized appropriately, potentially causing a buffer overflow if `ActualDestLen` exceeds `LargerDestLenEstimate`.

#### Summary of changes

- - Migrated the zlib example to use WIT (WebAssembly Interface Types) for Emscripten builds, including the inclusion of generated headers and adjustments for compatibility with WIT-bindgen.
- Replaced custom `zlib` function implementations with conditionally defined native or WebAssembly imports, providing a seamless interface based on the build environment.
- Introduced helper functions (`vecToListU8`, `strToComponentString`) to convert between C++ data structures and those expected by the WIT-bindgen generated ABI layer.

## [examples/plugin/wasmedge-zlib/wit/world.wit](https://github.com/WasmEdge/WasmEdge/blob/6461cd0f709f958a086ec884a352622e064444c7/examples%2Fplugin%2Fwasmedge-zlib%2Fwit%2Fworld.wit)

#### Potential issues

1. **Package Declaration Error**: The package declaration `package example:zlib@0.1.0;` is incorrectly formatted. In many languages, the version should not be included in the package declaration.
2. **Incorrect World Syntax**: The `world zlib-component { export compressor; }` syntax appears to be incorrect or non-standard. Ensure this aligns with the expected syntax for defining and exporting components in your language or framework.
3. **Undefined Component**: The component `compressor` is referenced but not defined within the provided code snippet, leading to a potential compilation error unless defined elsewhere.

#### Summary of changes

- • Introduced a new `package` declaration for `example:zlib@0.1.0`.
- Defined a `world` named `zlib-component` to encapsulate the example.
- Exported a component named `compressor` from the `zlib-component` world.

## [examples/plugin/wasmedge-zlib/wit/zlib.wit](https://github.com/WasmEdge/WasmEdge/blob/6461cd0f709f958a086ec884a352622e064444c7/examples%2Fplugin%2Fwasmedge-zlib%2Fwit%2Fzlib.wit)

#### Potential issues

1. The `interface` keyword is incorrect in this context; it should be `type` since WebAssembly Interface Types use `type` for defining function types or interfaces.
2. The function signatures use `list<u8>` which is not a standard type in WebAssembly Text Format (WAT) or WASM, instead, you should use `vec<u8>`.
3. The return type `result<list<u8>, string>` is not valid in Wasm; Wasm does not have a built-in `Result` or `Option` type, and error handling typically needs to be managed through other means, such as using multiple return values or encoding errors differently.

#### Summary of changes

- * Introduced a new `interface` named `compressor` defining the expected functions for compression and decompression.
- Added `deflate` function to handle compression, returning either compressed data or an error message.
- Added `inflate` function to handle decompression, returning either decompressed data or an error message.


author_association: MEMBER
user: login: PhantomInTheWire
created_at: 2025-05-29T19:05:10Z
body: Quick update: I managed to get the bindings working. Linker errors were tricky, especially sanitizing the exported function names, since wit-bindgen uses characters like #, @, and . that em++ doesn’t handle well. The lack of pointer support in wit also added some extra complexity (and required a fair bit of creativity).

I’m currently updating the Makefile and README, and making sure everything is well-documented for both the build instructions and code comments, since this version has significantly more moving parts than the previous and initial implementations (especially for those unfamiliar with WIT). I should be done in about a day and will push the changes soon!
author_association: CONTRIBUTOR
user: login: hydai
created_at: 2025-05-31T22:31:22Z
body: Please run `clang-format` before submitting the code. It shows that the lint has failed.
author_association: MEMBER
user: login: PhantomInTheWire
created_at: 2025-05-31T23:01:50Z
body: it seems like the issue was because of v16 and 18 of clang-format
author_association: CONTRIBUTOR
user: login: hydai
created_at: 2025-05-31T23:04:18Z
body: Your last commit seems to break other files. I think you should apply `clang-format` only to `main.cpp`.
author_association: MEMBER
user: login: PhantomInTheWire
created_at: 2025-05-31T23:08:30Z
body: can't believe linting is the final boss 😭
author_association: CONTRIBUTOR