13 KiB
FFI → Direct Rust Bağımlılığı Geçiş Planı
Hedef
hcie-engine-api'de şu an dinamik .so üzerinden yüklenen tüm core rendering crate'lerini doğrudan Rust crate bağımlılığına çevirmek. Sadece AI ve Vision crate'leri FFI'de kalır (AI ajanlarının kod bozmasını engellemek için).
Bu sayede regression #1 (her composite'te 330MB FFI pixel copy) tamamen ortadan kalkar.
Kapsam
| Crate | Şu an | Yeni |
|---|---|---|
hcie-blend |
FFI .so |
✅ Direct Rust (zaten Cargo.toml'da var) |
hcie-brush-engine |
FFI .so |
✅ Direct Rust (zaten Cargo.toml'da var) |
hcie-draw |
FFI .so |
🆕 Cargo.toml'a ekle |
hcie-filter |
FFI .so |
🆕 Cargo.toml'a ekle |
hcie-composite |
FFI .so |
🆕 Cargo.toml'a ekle |
hcie-io |
FFI .so |
🆕 Cargo.toml'a ekle |
hcie-psd |
FFI .so |
🆕 Cargo.toml'a ekle (package = "psd") |
hcie-kra |
FFI .so |
🆕 Cargo.toml'a ekle |
hcie-native |
FFI .so |
🆕 Cargo.toml'a ekle |
hcie-vector |
FFI .so |
🆕 Cargo.toml'a ekle |
hcie-ai |
FFI .so |
🔒 FFI kalır |
hcie-vision |
FFI .so |
🔒 FFI kalır |
Adım Adım Değişiklikler
Adım 1: hcie-engine-api/Cargo.toml
Ekle:
hcie-draw = { path = "../hcie-draw" }
hcie-composite = { path = "../hcie-composite" }
hcie-filter = { path = "../hcie-filter" }
hcie-io = { path = "../hcie-io" }
hcie-psd = { path = "../hcie-psd", package = "psd" }
hcie-kra = { path = "../hcie-kra" }
hcie-native = { path = "../hcie-native" }
hcie-vector = { path = "../hcie-vector" }
Kaldır:
bincode = "1.3" # artık sadece FFI serileştirme için kullanılıyordu
libloading = "0.8" kalır (hcie-ai + hcie-vision için hala gerekli).
Adım 2: hcie-engine-api/src/dynamic_loader.rs
Tamamen yeniden yazılır. Sadece AI ve Vision kısımları FFI'de kalır.
Silinecek: ~900 satır (10 crate için FFI loader, symbol resolution, C struct tanımları)
Değişecek wrapper fonksiyonlar (imzaları aynı kalır, gövdeleri değişir):
| Eski | Yeni gövde |
|---|---|
blend_pixels(dst, src, mode, opacity) |
hcie_blend::blend_pixels(dst, src, mode, opacity) |
blend_buffers(dst, src, mode, opacity) |
hcie_blend::blend_buffers(dst, src, mode, opacity) (yeni pub fn eklenmeli) |
draw_line(layer, x0, y0, x1, y1, color, size, mask) |
hcie_draw::draw_line(x0, y0, x1, y1, &mut layer.pixels, ...) |
draw_filled_rect(layer, x1, y1, x2, y2, color, mask) |
hcie_draw::draw_filled_rect(x1, y1, x2, y2, ...) |
draw_filled_ellipse(layer, cx, cy, rx, ry, color, mask) |
hcie_draw::draw_filled_ellipse(cx, cy, rx, ry, ...) |
flood_fill(layer, x, y, color, tolerance, mask) |
hcie_draw::flood_fill(x, y, color, tolerance, ...) |
draw_brush_stroke(layer, points, color, tip, ...) |
hcie_draw::draw_brush_stroke(points, &mut layer.pixels, ...) |
draw_specialized_stroke(pixels, w, h, ...) |
hcie_brush_engine::draw_specialized_stroke(pixels, w, h, ...) |
apply_filter(id, params, pixels, w, h) |
hcie_filter::apply_filter(...) (Layer wrapper gerekli) |
composite_layers(layers, w, h) → Vec<u8> |
hcie_composite::composite_layers(...) (Layer dönüşümü gerekli) |
composite_layers_region(layers, w, h, x0, y0, x1, y1, out) |
hcie_composite::composite_layers_region(...) |
tiled::composite_tiled_into(layers, tiles, w, h, x0, y0, x1, y1, out) |
hcie_composite::tiled::composite_tiled_into(...) |
load_image(path) → Layer |
hcie_io::load_image(path) |
save_image(layer, path, format) |
hcie_io::save_image(layer, path, format) |
svg_import::import_svg(data) |
hcie_io::svg_import::import_svg(data) |
import_psd(path) → Vec<Layer> |
hcie_psd::import_psd(path) |
export_psd(layers, w, h, composited, path) |
hcie_psd::export_psd(layers, w, h, composited, path) |
import_kra(path) → Vec<Layer> |
hcie_kra::import_kra(path) |
export_kra(layers, w, h, composited, path) |
hcie_kra::export_kra(layers, w, h, composited, path) |
load_native(path) → Vec<Layer> |
hcie_native::load_native(path) |
save_native(layers, path) |
hcie_native::save_native(layers, path) |
vector::render_vector_shapes(layer) |
hcie_vector::render_vector_shapes(layer) |
vector::boolean_shapes(op, a, b) |
hcie_vector::path_boolean::boolean_shapes(op, a, b) |
Adım 3: hcie-engine-api/src/lib.rs — Use import güncellemesi
Tüm dynamic_loader::xxx çağrılarının olduğu satırlar (toplam 22 çağrı noktası) aynı isimdeki yeni wrapper'lara yönlendirilir. Çağrı imzaları değişmediği için sadece use import'ları güncellenir.
Kritik: composite_layers() ve tiled::composite_tiled_into() çağrılmadan önce &[hcie_protocol::Layer] → Vec<hcie_composite::Layer> dönüşümü yapılmalıdır. Bu dönüşüm mantığı zaten dynamic_loader::build_c_desc()'te mevcut — sadece çıktı tipi CCompositeLayerDesc yerine hcie_composite::Layer olacak.
Dönüşüm helper fonksiyonu (dynamic_loader.rs'ye veya lib.rs'ye eklenir):
fn protocol_layers_to_composite(layers: &[Layer]) -> Vec<hcie_composite::Layer> {
layers.iter().map(|l| {
let (pixels, w, h) = /* effects_cache check */;
hcie_composite::Layer {
pixels: pixels.to_vec(), // ← TEK COPY BURADA
width: w, height: h,
visible: l.visible, opacity: l.opacity,
blend_mode: l.blend_mode as i32,
clipping_mask: l.clipping_mask,
fill_opacity: l.fill_opacity,
mask_pixels: l.mask_pixels.clone(),
mask_bounds: l.mask_bounds,
mask_default_color: l.mask_default_color,
adjustment: l.adjustment.clone(),
effects: l.effects.clone(),
styles: l.styles.clone(),
}
}).collect()
}
Not: V3'te bu copy yoktu çünkü referansla çalışıyordu. Burada kaçınılmaz bir copy var (çünkü hcie_composite::Layer owned Vec<u8> bekler). Ama eskiden FFI'da hem CCompositeLayerDesc yapısı kuruluyordu hem de FFI içinde tekrar copy yapılıyordu (2 copy). Şimdi sadece 1 copy kalır.
Adım 4: Her Crate'te FFI Export Kodlarını Kaldır
Her crate'in lib.rs'sinden #[no_mangle] pub unsafe extern "C" fn fonksiyonları silinir. crate-type'dan cdylib kaldırılır.
hcie-blend:
Cargo.toml:crate-type→["staticlib", "rlib"]lib.rs: Silblend_pixels_c,blend_buffers_clib.rs: Eklepub fn blend_buffers(dst: &mut [u8], src: &[u8], mode: BlendMode, opacity: f32)— gövdesiblend_buffers_cfonksiyonunun içinden alınır (rayon parallel loop)
hcie-draw:
Cargo.toml:crate-type→["staticlib", "rlib"]lib.rs: Sildraw_line_c,draw_filled_rect_c,draw_filled_circle_c,flood_fill_c,draw_brush_stroke_c
hcie-filter:
Cargo.toml:crate-type→["staticlib", "rlib"]lib.rs: Silapply_filter_c,get_filter_ids_json_c,free_filter_list_string_c
hcie-composite:
Cargo.toml:crate-type→["staticlib", "rlib"]lib.rs: Silcomposite_layers_c,composite_layers_region_c,composite_tiled_clib.rs:hcie_protocol'u dev-dependencies'ten regular dependency'e çek (Layer tipini kullanmak için)
hcie-io:
Cargo.toml:crate-type→["staticlib", "rlib"],ffifeature'ını kaldırlib.rs: Silload_image_c,save_image_c,import_svg_c,free_buffer_cve#[cfg(feature = "ffi")]blokları
hcie-psd:
Cargo.toml:crate-type→["rlib"],ffifeature'ını kaldırpsd/src/lib.rsveyaffi.rs: Silimport_psd_c,export_psd_c,free_buffer_c
hcie-kra:
Cargo.toml:crate-type→["rlib"],ffifeature'ını kaldırlib.rs: Silimport_kra_c,export_kra_c,kra_free_buffer_c
hcie-native:
Cargo.toml:crate-type→["rlib"],ffifeature'ını kaldırlib.rs: Silload_native_c,save_native_c,free_buffer_c
hcie-brush-engine:
Cargo.toml:crate-type→["staticlib", "rlib"]lib.rs: Sildraw_specialized_stroke_c
hcie-vector:
Cargo.toml:crate-type→["staticlib", "rlib"]lib.rs: Silrender_vector_shapes_c,vector_boolean_shapes_c,free_buffer_c
Adım 5: Build Script Güncellemesi
build_and_copy_plugins.sh:
- Sadece
hcie-aivehcie-visionbuild adımları kalır (step 12, 13) - Step 1-11 (hcie-color, hcie-blend, hcie-brush-engine, hcie-draw, hcie-composite, hcie-filter, hcie-io, hcie-vector, psd, hcie-kra, hcie-native) kaldırılır
build_brush_engine.sh:
- Tamamen silinebilir (hcie-brush-engine .so build'i build_and_copy_plugins.sh step 3 ile aynı)
Adım 6: Derleme ve Doğrulama
cargo check --workspace # workspace üyeleri
cd hcie-engine-api && cargo check # engine-api
Risk Değerlendirmesi
| Değişiklik | Risk | Açıklama |
|---|---|---|
hcie-blend → direct |
Düşük | İmzalar birebir aynı. Sadece blend_buffers Rust API'si eklenmeli. |
hcie-draw → direct |
Düşük | İmzalar birebir aynı (raw pixel buffer). |
hcie-brush-engine → direct |
Düşük | İmzalar birebir aynı. Zaten bağımlılık var. |
hcie-filter → direct |
Orta | hcie_filter::Layer tipi farklı. Dynamic loader'da (&mut [u8], u32, u32) → hcie_filter::Layer wrapper yazılmalı. |
hcie-composite → direct |
Orta-Yüksek | hcie_composite::Layer tipi farklı. build_c_desc() mantığı hcie_composite::Layer'e uyarlanmalı. 1 adet pixel copy kaçınılmaz (FFI'da 2 copy vardı). |
hcie-io → direct |
Düşük | İmzalar birebir aynı. Aynı hcie_protocol::Layer tipi. |
hcie-psd / hcie-kra / hcie-native |
Orta | Rust API imzaları kontrol edilmeli, büyük olasılıkla uyumlu. |
hcie-vector → direct |
Düşük | render_vector_shapes(&mut Layer) aynı. boolean_shapes path_boolean modülünde. |
| Build script değişikliği | Düşük | Sadece .so build adımları kaldırılır. |
| Plugin arama kodu | Düşük | Sadece AI/Vision için kalır. |
Toplam Değişiklik İstatistiği (Tahmini)
| Dosya | Değişiklik |
|---|---|
hcie-engine-api/Cargo.toml |
+9 satır, -1 satır |
hcie-engine-api/src/dynamic_loader.rs |
~900 satır silinir, ~200 satır yeniden yazılır |
hcie-engine-api/src/lib.rs |
~5 satır import değişikliği |
10 crate'in lib.rs'si |
~30-80 satır FFI export silinir/her crate |
10 crate'in Cargo.toml'u |
crate-type ve feature değişikliği |
build_and_copy_plugins.sh |
~80 satır silinir (~110 → ~30) |
build_brush_engine.sh |
silinir (~30 satır) |
Toplam: ~300 satır eklenir, ~1300 satır silinir, ~100 satır değişir.
Ek: Workspace + Git Hooks + Lock Güncellemesi
FFI→direct dönüşümüne paralel olarak yapıldı:
Kök Workspace (Cargo.toml)
/mnt/extra/00_PROJECTS/hcie-rust-v4/Cargo.toml— tüm 31 crate member olarak listelendi- Eski workspace'ler (
hcie-egui-app/Cargo.toml,hcie-core-app/Cargo.toml) → regular package'a çevrildi - Tüm workspace dependency'leri (egui 0.34, serde, rayon, image vs.) root'tan yönetilir
- V3'teki
LOCKED_PERF_PROFILESbloğu korundu
Versiyon Çakışmaları Çözüldü
| Çakışma | Çözüm |
|---|---|
| egui 0.27/0.28/0.29/0.34 | Tümü 0.34'e çekildi (7 crate'te dev-dep güncellendi) |
| eframe 0.27/0.28/0.29/0.34 | Tümü 0.34'e çekildi |
| fontdue 0.7/0.9 | hcie-text 0.9'a çekildi |
| rfd 0.14/0.15 | hcie-io dev-dep 0.15'e çekildi |
Git Hook Sistemi
V3'teki semantic etki analizi sistemi .githooks/ dizinine kuruldu:
| Dosya | Açıklama |
|---|---|
.githooks/pre-commit |
Staged değişiklikleri project_manifest.json ile karşılaştırır. HIGH blast radius varsa cargo test zorunlu kılar, başarısızsa commit'i engeller. |
.githooks/post-commit |
Commit sonrası generate_semantic_report.py ile 3 katmanlı rapor üretir (Layer 1: bağımlılık grafiği, Layer 2: API diff, Layer 3: semver opsiyonel). |
.githooks/semantic_analyzer.py |
Pre-commit analiz motoru |
.githooks/generate_semantic_report.py |
3 katmanlı raportör (1075 satır, V3'ten port edildi) |
.githooks/semantic_check.sh |
CLI wrapper (precommit/audit/full/quick/json) |
project_manifest.json |
105 dosya entry'si, 23 crate, V3'ten uyarlanmış path'ler |
Kurulum:
git config core.hooksPath .githooks
.gitignore
- Kök
.gitignore→/target/ile tüm crate'ler tek target paylaşır - Eski
hcie-egui-app/.gitignoreartık geçerli değil (workspace root'taki geçerli)
lock.sh / unlock.sh
- Liste güncellendi:
hcie-pixel-bridgeunlock'ta gereksizdi → kaldırıldı - FFI→direct sonrası
.sobuild gerektirmeyen crate'ler de lock listesinde kalır (kaynak kodu AI ajanlarından korumak için)