teamy-vox-codegen 0.10.0-rc.9

Language bindings codegen for vox
Documentation
pub mod java;
pub mod swift;
pub mod typescript;

use facet_core::Shape;
use vox_types::{ServiceDescriptor, ShapeKind, StructInfo, VariantKind, classify_shape};

pub(crate) fn validate_no_fd_shapes(service: &ServiceDescriptor, target: &str) {
    for method in service.methods {
        for arg in method.args {
            assert!(
                !shape_contains_fd(arg.shape),
                "{target} codegen does not support vox::Fd capabilities: {}.{} argument `{}` requires an fd-capable Rust/local transport",
                method.service_name,
                method.method_name,
                arg.name
            );
            if let Some(element) = arg.channel_element {
                assert!(
                    !shape_contains_fd(element),
                    "{target} codegen does not support vox::Fd channel items: {}.{} argument `{}` requires an fd-capable Rust/local transport",
                    method.service_name,
                    method.method_name,
                    arg.name
                );
            }
        }
        assert!(
            !shape_contains_fd(method.return_shape),
            "{target} codegen does not support vox::Fd capabilities: {}.{} return type requires an fd-capable Rust/local transport",
            method.service_name,
            method.method_name
        );
    }
}

fn shape_contains_fd(shape: &'static Shape) -> bool {
    let mut seen = std::collections::HashSet::new();
    shape_contains_fd_inner(shape, &mut seen)
}

fn shape_contains_fd_inner(
    shape: &'static Shape,
    seen: &mut std::collections::HashSet<usize>,
) -> bool {
    if vox_types::is_fd(shape) {
        return true;
    }
    if !seen.insert(shape as *const Shape as usize) {
        return false;
    }

    match classify_shape(shape) {
        ShapeKind::List { element }
        | ShapeKind::Slice { element }
        | ShapeKind::Option { inner: element }
        | ShapeKind::Array { element, .. }
        | ShapeKind::Set { element }
        | ShapeKind::Tx { inner: element }
        | ShapeKind::Rx { inner: element }
        | ShapeKind::Pointer { pointee: element } => shape_contains_fd_inner(element, seen),
        ShapeKind::Map { key, value } => {
            shape_contains_fd_inner(key, seen) || shape_contains_fd_inner(value, seen)
        }
        ShapeKind::Tuple { elements } => elements
            .iter()
            .any(|param| shape_contains_fd_inner(param.shape, seen)),
        ShapeKind::TupleStruct { fields } | ShapeKind::Struct(StructInfo { fields, .. }) => fields
            .iter()
            .any(|field| shape_contains_fd_inner(field.shape(), seen)),
        ShapeKind::Enum(info) => {
            info.variants
                .iter()
                .any(|variant| match vox_types::classify_variant(variant) {
                    VariantKind::Unit => false,
                    VariantKind::Newtype { inner } => shape_contains_fd_inner(inner, seen),
                    VariantKind::Tuple { fields } | VariantKind::Struct { fields } => fields
                        .iter()
                        .any(|field| shape_contains_fd_inner(field.shape(), seen)),
                })
        }
        ShapeKind::Result { ok, err } => {
            shape_contains_fd_inner(ok, seen) || shape_contains_fd_inner(err, seen)
        }
        ShapeKind::Scalar(_) | ShapeKind::Opaque => false,
    }
}