You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(ffi-skill): swap canonical example to FFI_CatalogProvider, trim template comments
FFI_TableProvider has async, capability-flag, and session-handling surface
that obscures the structural pattern. FFI_CatalogProvider shows the full
shape (codec, nested FFI types, FFI_Option/FFI_Result, Arc-backed
PrivateData) without that noise; cite FFI_TableProvider only in the
sections where its complexity earns its keep. Also strip per-field
comments from the struct skeleton — they duplicated source doc-comments
and pattern guidance now lives in the "Field rules" bullet list below.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .ai/skills/datafusion-ffi/SKILL.md
+10-17Lines changed: 10 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,25 +32,16 @@ Trigger this skill any time the work touches `datafusion/ffi/`:
32
32
33
33
## The standard wrapper shape
34
34
35
-
A new `FFI_X` for trait `X` must follow this template. Use `FFI_TableProvider` (src/table_provider.rs) and `FFI_CatalogProvider` (src/catalog_provider.rs) as canonical references.
35
+
A new `FFI_X` for trait `X` must follow this template. Use `FFI_CatalogProvider` (`src/catalog_provider.rs`) as the canonical reference — it shows the full shape (codec field, nested FFI types, `FFI_Option`/`FFI_Result` returns, Arc-backed `PrivateData`) without async or capability-flag noise. `FFI_TableProvider` (`src/table_provider.rs`) covers async (`scan`, `FFI_SessionRef`, `FfiFuture`) and the one `Option<fn>` capability flag (`supports_filters_pushdown`).
36
36
37
37
### 1. The `FFI_X` struct
38
38
39
39
```rust
40
40
#[repr(C)]
41
41
#[derive(Debug)]
42
42
pubstructFFI_X {
43
-
// One unsafe extern "C" fn per trait method (see § "Method coverage" below).
44
-
// Always populate this — calling through `Arc<dyn Trait>` dispatches to the
45
-
// override if there is one, else to the trait default. The producer side
46
-
// gets the right answer either way without the consumer needing to know.
// Codec only if the trait moves Exprs/Plans across the boundary.
54
45
publogical_codec:FFI_LogicalExtensionCodec,
55
46
56
47
clone:unsafeextern"C"fn(&Self) ->Self,
@@ -61,17 +52,19 @@ pub struct FFI_X {
61
52
publibrary_marker_id:extern"C"fn() ->usize,
62
53
}
63
54
64
-
// Pick bounds to match the wrapped trait (see rule 4).
65
-
// Most wrappers want both; `Send`-only for streams / mutable traits.
66
55
unsafeimplSendforFFI_X {}
67
56
unsafeimplSyncforFFI_X {}
68
57
```
69
58
70
-
Notes:
59
+
Field rules:
71
60
72
-
- Method function pointers are private by default. Mark `pub` only if a downstream library needs to invoke them directly (rare — usually only `version`, `library_marker_id`, embedded codecs are public).
73
-
-`version: super::version` is mandatory. Consumers gate compatibility on it.
74
-
-`library_marker_id: crate::get_library_marker_id` is mandatory. It powers local-bypass.
61
+
-**One `unsafe extern "C" fn` per trait method.** Always populate — `Arc<dyn Trait>` dispatch picks override-or-default at call time, so the producer side gets the right answer without the consumer needing to know. See § "Method coverage".
62
+
-**`Option<fn>` is the capability-flag exception**, not a template. Crate uses it exactly once: `FFI_TableProvider::supports_filters_pushdown`. See § "Method coverage".
63
+
-**Codec field** (`FFI_LogicalExtensionCodec` / `FFI_PhysicalExtensionCodec`) only if the trait moves `Expr`s / `LogicalPlan`s / `ExecutionPlan`s across the boundary.
64
+
-**Method function pointers are private by default.** Mark `pub` only if a downstream library needs to invoke them directly (rare — typically only `version`, `library_marker_id`, embedded codecs are `pub`).
65
+
-**`version: super::version` is mandatory.** Consumers gate compatibility on it.
66
+
-**`library_marker_id: crate::get_library_marker_id` is mandatory.** Powers local-bypass.
67
+
-**`Send`/`Sync` bounds match the wrapped trait** (rule 4). Most wrappers want both; `Send`-only for streams / mutable traits.
75
68
76
69
### 2. `PrivateData` shape
77
70
@@ -341,7 +334,7 @@ When reviewing a PR that touches `datafusion/ffi/`:
0 commit comments