---
source: tests/backends_swift_snapshot_test.rs
expression: "&file.content"
---
// Generated by alef. Do not edit by hand.

#![allow(unused_variables, unreachable_code, unreachable_patterns)]
#![allow(
    clippy::collapsible_if,
    clippy::collapsible_match,
    clippy::needless_borrows_for_generic_args,
    clippy::field_reassign_with_default,
    clippy::too_many_arguments,
    clippy::clone_on_copy,
    clippy::unnecessary_cast,
    clippy::manual_flatten,
    clippy::match_single_binding,
    clippy::redundant_closure,
    clippy::useless_conversion,
    clippy::inherent_to_string,
)]


/// Process-wide tokio runtime shared across every swift-bridge async wrapper.
///
/// alef-emitted; see shims.rs for the rationale (orphaned reqwest connection
/// pools when each call creates and drops its own current-thread runtime).
fn __alef_tokio_runtime() -> &'static ::tokio::runtime::Runtime {
    use std::sync::OnceLock;
    static RT: OnceLock<::tokio::runtime::Runtime> = OnceLock::new();
    RT.get_or_init(|| {
        ::tokio::runtime::Builder::new_multi_thread()
            .enable_all()
            .build()
            .expect("build process-wide alef tokio runtime")
    })
}

#[swift_bridge::bridge]
mod ffi {
    extern "Rust" {
        type ImageConfig;
        #[swift_bridge(init)]
        fn new(language: String) -> ImageConfig;
        fn language(&self) -> String;
    }

    extern "Rust" {
        type ProcessingResult;
        #[swift_bridge(init)]
        fn new(text: String) -> ProcessingResult;
        fn text(&self) -> String;
    }

    extern "Rust" {
        type ImageProcessorBox;
        fn alef_phantom_vec_image_processor() -> Vec<ImageProcessorBox>;
        fn image_processor_call_process_image(this: &ImageProcessorBox, image_bytes: Vec<u8>, config: ImageConfig) -> String;
        fn image_processor_call_supports_language(this: &ImageProcessorBox, lang: String) -> bool;
    }

    extern "Rust" {
        #[swift_bridge(swift_name = "registerImageProcessor")]
        fn register_image_processor(swift_box: SwiftImageProcessorBox) -> Result<(), String>;
        #[swift_bridge(swift_name = "unregisterImageProcessor")]
        fn unregister_image_processor(name: String) -> Result<(), String>;
    }

    extern "Swift" {
        type SwiftImageProcessorBox;
        fn alef_name(&self) -> String;
        fn alef_version(&self) -> String;
        fn alef_initialize(&self) -> String;
        fn alef_shutdown(&self) -> String;
        fn alef_process_image(&self, image_bytes: Vec<u8>, config: String) -> String;
        fn alef_supports_language(&self, lang: String) -> bool;
    }

    extern "Rust" {
        #[swift_bridge(swift_name = "imageConfigFromJson")]
        fn image_config_from_json(json: String) -> Result<ImageConfig, String>;
    }
    extern "Rust" {
        #[swift_bridge(swift_name = "processingResultFromJson")]
        fn processing_result_from_json(json: String) -> Result<ProcessingResult, String>;
    }
}


pub struct ImageConfig(pub demo::ImageConfig);
impl ImageConfig {
    pub fn new(language: String) -> ImageConfig {
        let mut __target: demo::ImageConfig = ::std::default::Default::default();
        {
            // Try JSON parse first (handles enum/object values); on parse failure
            // treat the raw input as a JSON string scalar so plain `String` /
            // string-like enum fields don't end up empty for inputs that aren't
            // valid JSON tokens (e.g. `tts-1`).
            let __v = ::serde_json::from_str::<::serde_json::Value>(&language)
                .unwrap_or(::serde_json::Value::String(language.clone()));
            if let Ok(t) = ::serde_json::from_value(__v) { __target.language = t; }
        }
        ImageConfig(__target)
    }
    pub fn language(&self) -> String {
        self.0.language.clone()
    }
}

pub struct ProcessingResult(pub demo::ProcessingResult);
impl ProcessingResult {
    pub fn new(text: String) -> ProcessingResult {
        let mut __target: demo::ProcessingResult = ::std::default::Default::default();
        {
            // Try JSON parse first (handles enum/object values); on parse failure
            // treat the raw input as a JSON string scalar so plain `String` /
            // string-like enum fields don't end up empty for inputs that aren't
            // valid JSON tokens (e.g. `tts-1`).
            let __v = ::serde_json::from_str::<::serde_json::Value>(&text)
                .unwrap_or(::serde_json::Value::String(text.clone()));
            if let Ok(t) = ::serde_json::from_value(__v) { __target.text = t; }
        }
        ProcessingResult(__target)
    }
    pub fn text(&self) -> String {
        self.0.text.clone()
    }
}

pub struct ImageProcessorBox(pub Box<dyn demo::plugins::ImageProcessor + Send + Sync>);
#[doc(hidden)]
pub fn alef_phantom_vec_image_processor() -> Vec<ImageProcessorBox> { Vec::new() }
pub fn image_processor_call_process_image(this: &ImageProcessorBox, image_bytes: Vec<u8>, config: ImageConfig) -> String {
    crate::__alef_tokio_runtime().block_on(async { match this.0.process_image(&image_bytes, &config.0).await {
    Ok(v) => format!("{{\"ok\": {}}}", serde_json::to_string(&v).expect("serializable return")),
    Err(e) => format!("{{\"err\": {}}}", serde_json::to_string(&e.to_string()).expect("serializable error")),
} })
}
pub fn image_processor_call_supports_language(this: &ImageProcessorBox, lang: String) -> bool {
    this.0.supports_language(&lang)
}

/// Convert a stringified Swift error into the configured source-crate error type.
#[allow(dead_code)]
fn plugin_error_from_string(message: String) -> demo::Error {
    demo::Error::from(message)
}

/// JSON envelope returned by every fallible Swift trait method. Carries `Ok(T)`
/// as `{"ok": <serialised T>}` and `Err(String)` as `{"err": "<message>"}`.
/// Avoids swift-bridge 0.1.59's broken `Result<RustString, RustString>` codegen.
#[allow(dead_code)]
#[derive(::serde::Deserialize)]
#[serde(rename_all = "snake_case")]
enum InboundEnvelope<T> { Ok(T), Err(String) }

/// Deserialise a JSON envelope returned from a Swift FFI shim into a typed Result.
#[allow(dead_code)]
fn decode_inbound_envelope<T>(json: &str) -> std::result::Result<T, demo::Error>
where
    T: ::serde::de::DeserializeOwned,
{
    match ::serde_json::from_str::<InboundEnvelope<T>>(json) {
        Ok(InboundEnvelope::Ok(value)) => Ok(value),
        Ok(InboundEnvelope::Err(message)) => Err(plugin_error_from_string(message)),
        Err(e) => Err(plugin_error_from_string(format!("swift returned malformed envelope: {e}"))),
    }
}
/// Rust-side wrapper around a Swift class implementing the `ImageProcessor` plugin protocol.
///
/// The Swift instance is held via a `swift-bridge` opaque handle that retains
/// the underlying ARC reference for the lifetime of this struct. Send + Sync are
/// asserted unsafely: Swift classes used as generated plugins must be thread-safe
/// (the `Plugin` super-trait requires it), and ARC handles themselves are safe to share.
pub struct SwiftImageProcessorWrapper {
    inner: ffi::SwiftImageProcessorBox,
    /// Cached `Plugin::name()` — required because the trait returns `&str` but
    /// the Swift FFI shim returns an owned `String`. Populated lazily on first access.
    name_cache: ::std::sync::OnceLock<String>,
}
unsafe impl Send for SwiftImageProcessorWrapper {}
unsafe impl Sync for SwiftImageProcessorWrapper {}

impl SwiftImageProcessorWrapper {
    /// Construct a new wrapper from a Swift `SwiftImageProcessorBox` handle.
    pub fn new(inner: ffi::SwiftImageProcessorBox) -> Self {
        Self { inner, name_cache: ::std::sync::OnceLock::new() }
    }
}
impl demo::plugins::Plugin for SwiftImageProcessorWrapper {
    fn name(&self) -> &str {
        self.name_cache.get_or_init(|| self.inner.alef_name()).as_str()
    }

    fn version(&self) -> String {
        self.inner.alef_version()
    }

    fn initialize(&self) -> std::result::Result<(), demo::Error> {
        decode_inbound_envelope::<()>(&self.inner.alef_initialize()).map(|_| ())
    }

    fn shutdown(&self) -> std::result::Result<(), demo::Error> {
        decode_inbound_envelope::<()>(&self.inner.alef_shutdown()).map(|_| ())
    }
}
#[async_trait::async_trait]
impl demo::plugins::ImageProcessor for SwiftImageProcessorWrapper {
    async fn process_image(&self, image_bytes: &[u8], config: &demo::ImageConfig) -> std::result::Result<demo::ProcessingResult, demo::Error> {
        let image_bytes = image_bytes.to_vec();
        let config = ::serde_json::to_string(&config).expect("serializable param config");
        let envelope = self.inner.alef_process_image(image_bytes, config);
        decode_inbound_envelope::<demo::ProcessingResult>(&envelope)
    }

    fn supports_language(&self, lang: &str) -> bool {
        let lang = lang.to_string();
        self.inner.alef_supports_language(lang)
    }

}

/// Register a Swift class implementation as a `ImageProcessor` plugin.
///
/// Wraps the Swift handle in `Arc<SwiftXxxWrapper>` and inserts it into the host registry.
/// Errors from the registry are stringified for swift-bridge transport.
pub fn register_image_processor(swift_box: ffi::SwiftImageProcessorBox) -> Result<(), String> {
    let arc: ::std::sync::Arc<dyn demo::plugins::ImageProcessor> = ::std::sync::Arc::new(SwiftImageProcessorWrapper::new(swift_box));
    let registry = demo::plugins::registry::get_image_processor_registry();
    let mut guard = registry.write();
    guard.register(arc).map_err(|e| e.to_string())
}
/// Unregister a previously-registered `ImageProcessor` plugin by name.
pub fn unregister_image_processor(name: String) -> Result<(), String> {
    let registry = demo::plugins::registry::get_image_processor_registry();
    let mut guard = registry.write();
    guard.remove(&name).map_err(|e| e.to_string())
}


pub fn image_config_from_json(json: String) -> Result<ImageConfig, String> {
    serde_json::from_str::<demo::ImageConfig>(&json)
        .map(ImageConfig)
        .map_err(|e| e.to_string())
}
pub fn processing_result_from_json(json: String) -> Result<ProcessingResult, String> {
    serde_json::from_str::<demo::ProcessingResult>(&json)
        .map(ProcessingResult)
        .map_err(|e| e.to_string())
}
