Add interface struct declarations
diff --git a/doc/changelog.md b/doc/changelog.md
index f04191e..5f54bdf 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -3,6 +3,7 @@
 
 ## Work In Progress
 
+- Added interfaces.
 - Renamed warnings to notes.
 - Made `wuffs_base__pixel_format` a struct.
 - Made `wuffs_base__pixel_subsampling` a struct.
diff --git a/internal/cgen/base/all-impl.c b/internal/cgen/base/all-impl.c
index 8289d71..e611e85 100644
--- a/internal/cgen/base/all-impl.c
+++ b/internal/cgen/base/all-impl.c
@@ -42,6 +42,8 @@
 
 // !! INSERT base/all-public.h.
 
+// !! INSERT InterfaceDeclarations.
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
@@ -112,6 +114,8 @@
 
 // !! INSERT wuffs_base__status strings.
 
+// !! INSERT InterfaceDefinitions.
+
 // !! INSERT base/image-impl.c.
 
 #endif  // !defined(WUFFS_CONFIG__MODULES) ||
diff --git a/internal/cgen/cgen.go b/internal/cgen/cgen.go
index 1f568c6..9100f23 100644
--- a/internal/cgen/cgen.go
+++ b/internal/cgen/cgen.go
@@ -117,10 +117,12 @@
 			}
 			buf := make(buffer, 0, 128*1024)
 			if err := expandBangBangInsert(&buf, baseAllImplC, map[string]func(*buffer) error{
-				"// !! INSERT base/all-private.h.\n": insertBaseAllPrivateH,
-				"// !! INSERT base/all-public.h.\n":  insertBaseAllPublicH,
-				"// !! INSERT base/copyright\n":      insertBaseCopyright,
-				"// !! INSERT base/image-impl.c.\n":  insertBaseImageImplC,
+				"// !! INSERT InterfaceDeclarations.\n": insertInterfaceDeclarations,
+				"// !! INSERT InterfaceDefinitions.\n":  insertInterfaceDefinitions,
+				"// !! INSERT base/all-private.h.\n":    insertBaseAllPrivateH,
+				"// !! INSERT base/all-public.h.\n":     insertBaseAllPublicH,
+				"// !! INSERT base/copyright\n":         insertBaseCopyright,
+				"// !! INSERT base/image-impl.c.\n":     insertBaseImageImplC,
 				"// !! INSERT wuffs_base__status strings.\n": func(b *buffer) error {
 					for _, z := range builtin.Statuses {
 						msg, _ := t.Unescape(z)
@@ -322,6 +324,62 @@
 	return nil
 }
 
+func insertInterfaceDeclarations(buf *buffer) error {
+	buf.writes("// ---------------- Interface Declarations.\n\n")
+	for _, n := range builtin.Interfaces {
+		buf.printf("extern const char* wuffs_base__%s__vtable_name;\n", n)
+		buf.writeb('\n')
+
+		buf.printf("typedef struct wuffs_base__%s__struct wuffs_base__%s;\n", n, n)
+		buf.writeb('\n')
+
+		buf.writes("#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)\n\n")
+
+		buf.printf("struct wuffs_base__%s__struct {", n)
+		buf.writes(`
+			#ifdef WUFFS_IMPLEMENTATION
+
+			struct {
+				uint32_t magic;
+				uint32_t active_coroutine;
+				wuffs_base__vtable first_vtable;
+			} private_impl;
+
+			#else  // WUFFS_IMPLEMENTATION
+
+			private:
+			union {
+				uint32_t align_as_per_magic_field;
+				uint8_t placeholder[1073741824];  // 1 GiB.
+			} private_impl WUFFS_BASE__POTENTIALLY_UNUSED_FIELD;
+
+			public:
+
+			#endif  // WUFFS_IMPLEMENTATION
+		`)
+
+		buf.writes("\n#ifdef __cplusplus\n\n")
+		// TODO: C++ methods.
+		buf.writes("#endif  // __cplusplus\n\n")
+
+		buf.printf("};  // struct wuffs_base__%s__struct\n\n", n)
+
+		buf.writes("#endif  // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)\n\n")
+	}
+	return nil
+}
+
+func insertInterfaceDefinitions(buf *buffer) error {
+	buf.writes("// ---------------- Interface Definitions.\n\n")
+	for _, n := range builtin.Interfaces {
+		buf.printf("const char* wuffs_base__%s__vtable_name = "+
+			"\"{vtable}wuffs_base__%s\";\n", n, n)
+	}
+	buf.writeb('\n')
+
+	return nil
+}
+
 type gen struct {
 	pkgPrefix string // e.g. "wuffs_jpeg__"
 	pkgName   string // e.g. "jpeg"
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 720448d..9d7195e 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -17,10 +17,10 @@
 package cgen
 
 const baseAllImplC = "" +
-	"#ifndef WUFFS_INCLUDE_GUARD__BASE\n#define WUFFS_INCLUDE_GUARD__BASE\n\n#if defined(WUFFS_IMPLEMENTATION) && !defined(WUFFS_CONFIG__MODULES)\n#define WUFFS_CONFIG__MODULES\n#define WUFFS_CONFIG__MODULE__BASE\n#endif\n\n// !! WUFFS MONOLITHIC RELEASE DISCARDS EVERYTHING ABOVE.\n\n// !! INSERT base/copyright\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <string.h>\n\n// GCC does not warn for unused *static inline* functions, but clang does.\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// !! INSERT base/all-public.h.\n\n#ifdef __cplusplus\n}  // extern \"C\"\n#endif\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n// WUFFS C HEADER ENDS HERE.\n#ifdef WUFFS_IMPLEMENTATION\n\n// GCC does not warn for unused *static inline* functions, but clang does.\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// !! INSERT base/all-privat" +
-	"e.h.\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE)\n\nconst uint8_t wuffs_base__low_bits_mask__u8[9] = {\n    0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF,\n};\n\nconst uint16_t wuffs_base__low_bits_mask__u16[17] = {\n    0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,\n    0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,\n};\n\nconst uint32_t wuffs_base__low_bits_mask__u32[33] = {\n    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F,\n    0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,\n    0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF,\n    0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,\n    0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF,\n    0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,\n};\n\nconst uint64_t wuffs_base__low_bits_mask__u64[65] = {\n    0x0000000000000000, 0x0000000000000001, 0x0000000000000003,\n    0x0000000000000007, 0x00000" +
-	"0000000000F, 0x000000000000001F,\n    0x000000000000003F, 0x000000000000007F, 0x00000000000000FF,\n    0x00000000000001FF, 0x00000000000003FF, 0x00000000000007FF,\n    0x0000000000000FFF, 0x0000000000001FFF, 0x0000000000003FFF,\n    0x0000000000007FFF, 0x000000000000FFFF, 0x000000000001FFFF,\n    0x000000000003FFFF, 0x000000000007FFFF, 0x00000000000FFFFF,\n    0x00000000001FFFFF, 0x00000000003FFFFF, 0x00000000007FFFFF,\n    0x0000000000FFFFFF, 0x0000000001FFFFFF, 0x0000000003FFFFFF,\n    0x0000000007FFFFFF, 0x000000000FFFFFFF, 0x000000001FFFFFFF,\n    0x000000003FFFFFFF, 0x000000007FFFFFFF, 0x00000000FFFFFFFF,\n    0x00000001FFFFFFFF, 0x00000003FFFFFFFF, 0x00000007FFFFFFFF,\n    0x0000000FFFFFFFFF, 0x0000001FFFFFFFFF, 0x0000003FFFFFFFFF,\n    0x0000007FFFFFFFFF, 0x000000FFFFFFFFFF, 0x000001FFFFFFFFFF,\n    0x000003FFFFFFFFFF, 0x000007FFFFFFFFFF, 0x00000FFFFFFFFFFF,\n    0x00001FFFFFFFFFFF, 0x00003FFFFFFFFFFF, 0x00007FFFFFFFFFFF,\n    0x0000FFFFFFFFFFFF, 0x0001FFFFFFFFFFFF, 0x0003FFFFFFFFFFFF,\n    0x0007FFFFFFFFFFFF, 0x000FF" +
-	"FFFFFFFFFFF, 0x001FFFFFFFFFFFFF,\n    0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF,\n    0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF,\n    0x0FFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF,\n    0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,\n};\n\n// !! INSERT wuffs_base__status strings.\n\n// !! INSERT base/image-impl.c.\n\n#endif  // !defined(WUFFS_CONFIG__MODULES) ||\n        // defined(WUFFS_CONFIG__MODULE__BASE)\n\n#ifdef __cplusplus\n}  // extern \"C\"\n#endif\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n#endif  // WUFFS_IMPLEMENTATION\n\n// !! WUFFS MONOLITHIC RELEASE DISCARDS EVERYTHING BELOW.\n\n#endif  // WUFFS_INCLUDE_GUARD__BASE\n" +
+	"#ifndef WUFFS_INCLUDE_GUARD__BASE\n#define WUFFS_INCLUDE_GUARD__BASE\n\n#if defined(WUFFS_IMPLEMENTATION) && !defined(WUFFS_CONFIG__MODULES)\n#define WUFFS_CONFIG__MODULES\n#define WUFFS_CONFIG__MODULE__BASE\n#endif\n\n// !! WUFFS MONOLITHIC RELEASE DISCARDS EVERYTHING ABOVE.\n\n// !! INSERT base/copyright\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <string.h>\n\n// GCC does not warn for unused *static inline* functions, but clang does.\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// !! INSERT base/all-public.h.\n\n// !! INSERT InterfaceDeclarations.\n\n#ifdef __cplusplus\n}  // extern \"C\"\n#endif\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n// WUFFS C HEADER ENDS HERE.\n#ifdef WUFFS_IMPLEMENTATION\n\n// GCC does not warn for unused *static inline* functions, but clang does.\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {" +
+	"\n#endif\n\n// !! INSERT base/all-private.h.\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE)\n\nconst uint8_t wuffs_base__low_bits_mask__u8[9] = {\n    0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF,\n};\n\nconst uint16_t wuffs_base__low_bits_mask__u16[17] = {\n    0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,\n    0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,\n};\n\nconst uint32_t wuffs_base__low_bits_mask__u32[33] = {\n    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F,\n    0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,\n    0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF,\n    0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,\n    0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF,\n    0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,\n};\n\nconst uint64_t wuffs_base__low_bits_mask__u64[65] = {\n    0x0000000000000000, 0x0000000000000001, 0x000000000000" +
+	"0003,\n    0x0000000000000007, 0x000000000000000F, 0x000000000000001F,\n    0x000000000000003F, 0x000000000000007F, 0x00000000000000FF,\n    0x00000000000001FF, 0x00000000000003FF, 0x00000000000007FF,\n    0x0000000000000FFF, 0x0000000000001FFF, 0x0000000000003FFF,\n    0x0000000000007FFF, 0x000000000000FFFF, 0x000000000001FFFF,\n    0x000000000003FFFF, 0x000000000007FFFF, 0x00000000000FFFFF,\n    0x00000000001FFFFF, 0x00000000003FFFFF, 0x00000000007FFFFF,\n    0x0000000000FFFFFF, 0x0000000001FFFFFF, 0x0000000003FFFFFF,\n    0x0000000007FFFFFF, 0x000000000FFFFFFF, 0x000000001FFFFFFF,\n    0x000000003FFFFFFF, 0x000000007FFFFFFF, 0x00000000FFFFFFFF,\n    0x00000001FFFFFFFF, 0x00000003FFFFFFFF, 0x00000007FFFFFFFF,\n    0x0000000FFFFFFFFF, 0x0000001FFFFFFFFF, 0x0000003FFFFFFFFF,\n    0x0000007FFFFFFFFF, 0x000000FFFFFFFFFF, 0x000001FFFFFFFFFF,\n    0x000003FFFFFFFFFF, 0x000007FFFFFFFFFF, 0x00000FFFFFFFFFFF,\n    0x00001FFFFFFFFFFF, 0x00003FFFFFFFFFFF, 0x00007FFFFFFFFFFF,\n    0x0000FFFFFFFFFFFF, 0x0001FFFFFFFFFFFF, 0x0003FFFFFFFF" +
+	"FFFF,\n    0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x001FFFFFFFFFFFFF,\n    0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF,\n    0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF,\n    0x0FFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF,\n    0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,\n};\n\n// !! INSERT wuffs_base__status strings.\n\n// !! INSERT InterfaceDefinitions.\n\n// !! INSERT base/image-impl.c.\n\n#endif  // !defined(WUFFS_CONFIG__MODULES) ||\n        // defined(WUFFS_CONFIG__MODULE__BASE)\n\n#ifdef __cplusplus\n}  // extern \"C\"\n#endif\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n#endif  // WUFFS_IMPLEMENTATION\n\n// !! WUFFS MONOLITHIC RELEASE DISCARDS EVERYTHING BELOW.\n\n#endif  // WUFFS_INCLUDE_GUARD__BASE\n" +
 	""
 
 const baseImageImplC = "" +
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index a924694..5123e33 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -337,6 +337,10 @@
 		"dst: slice u8, dst_palette: slice u8, src: slice u8) u64",
 }
 
+var Interfaces = []string{
+	"hasher_u32",
+}
+
 // The "T1" and "T2" types here are placeholders for generic "slice T" or
 // "table T" types. After tokenizing (but before parsing) these XxxFunc strings
 // (e.g. in the lang/check package), replace "T1" and "T2" with "†" or "‡"
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 438a202..ba4572b 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -2563,6 +2563,43 @@
 
 #endif  // __cplusplus
 
+// ---------------- Interface Declarations.
+
+extern const char* wuffs_base__hasher_u32__vtable_name;
+
+typedef struct wuffs_base__hasher_u32__struct wuffs_base__hasher_u32;
+
+#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
+
+struct wuffs_base__hasher_u32__struct {
+#ifdef WUFFS_IMPLEMENTATION
+
+  struct {
+    uint32_t magic;
+    uint32_t active_coroutine;
+    wuffs_base__vtable first_vtable;
+  } private_impl;
+
+#else  // WUFFS_IMPLEMENTATION
+
+ private:
+  union {
+    uint32_t align_as_per_magic_field;
+    uint8_t placeholder[1073741824];  // 1 GiB.
+  } private_impl WUFFS_BASE__POTENTIALLY_UNUSED_FIELD;
+
+ public:
+
+#endif  // WUFFS_IMPLEMENTATION
+
+#ifdef __cplusplus
+
+#endif  // __cplusplus
+
+};  // struct wuffs_base__hasher_u32__struct
+
+#endif  // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
@@ -4656,6 +4693,11 @@
 const char* wuffs_base__error__unsupported_option = "#base: unsupported option";
 const char* wuffs_base__error__too_much_data = "#base: too much data";
 
+// ---------------- Interface Definitions.
+
+const char* wuffs_base__hasher_u32__vtable_name =
+    "{vtable}wuffs_base__hasher_u32";
+
 // ---------------- Images
 
 const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {