vox_codegen/targets/
mod.rs1pub mod java;
2pub mod swift;
3pub mod typescript;
4
5use facet_core::Shape;
6use vox_types::{ServiceDescriptor, ShapeKind, StructInfo, VariantKind, classify_shape};
7
8pub(crate) fn validate_no_fd_shapes(service: &ServiceDescriptor, target: &str) {
9 for method in service.methods {
10 for arg in method.args {
11 assert!(
12 !shape_contains_fd(arg.shape),
13 "{target} codegen does not support vox::Fd capabilities: {}.{} argument `{}` requires an fd-capable Rust/local transport",
14 method.service_name,
15 method.method_name,
16 arg.name
17 );
18 if let Some(element) = arg.channel_element {
19 assert!(
20 !shape_contains_fd(element),
21 "{target} codegen does not support vox::Fd channel items: {}.{} argument `{}` requires an fd-capable Rust/local transport",
22 method.service_name,
23 method.method_name,
24 arg.name
25 );
26 }
27 }
28 assert!(
29 !shape_contains_fd(method.return_shape),
30 "{target} codegen does not support vox::Fd capabilities: {}.{} return type requires an fd-capable Rust/local transport",
31 method.service_name,
32 method.method_name
33 );
34 }
35}
36
37fn shape_contains_fd(shape: &'static Shape) -> bool {
38 let mut seen = std::collections::HashSet::new();
39 shape_contains_fd_inner(shape, &mut seen)
40}
41
42fn shape_contains_fd_inner(
43 shape: &'static Shape,
44 seen: &mut std::collections::HashSet<usize>,
45) -> bool {
46 if vox_types::is_fd(shape) {
47 return true;
48 }
49 if !seen.insert(shape as *const Shape as usize) {
50 return false;
51 }
52
53 match classify_shape(shape) {
54 ShapeKind::List { element }
55 | ShapeKind::Slice { element }
56 | ShapeKind::Option { inner: element }
57 | ShapeKind::Array { element, .. }
58 | ShapeKind::Set { element }
59 | ShapeKind::Tx { inner: element }
60 | ShapeKind::Rx { inner: element }
61 | ShapeKind::Pointer { pointee: element } => shape_contains_fd_inner(element, seen),
62 ShapeKind::Map { key, value } => {
63 shape_contains_fd_inner(key, seen) || shape_contains_fd_inner(value, seen)
64 }
65 ShapeKind::Tuple { elements } => elements
66 .iter()
67 .any(|param| shape_contains_fd_inner(param.shape, seen)),
68 ShapeKind::TupleStruct { fields } | ShapeKind::Struct(StructInfo { fields, .. }) => fields
69 .iter()
70 .any(|field| shape_contains_fd_inner(field.shape(), seen)),
71 ShapeKind::Enum(info) => {
72 info.variants
73 .iter()
74 .any(|variant| match vox_types::classify_variant(variant) {
75 VariantKind::Unit => false,
76 VariantKind::Newtype { inner } => shape_contains_fd_inner(inner, seen),
77 VariantKind::Tuple { fields } | VariantKind::Struct { fields } => fields
78 .iter()
79 .any(|field| shape_contains_fd_inner(field.shape(), seen)),
80 })
81 }
82 ShapeKind::Result { ok, err } => {
83 shape_contains_fd_inner(ok, seen) || shape_contains_fd_inner(err, seen)
84 }
85 ShapeKind::Scalar(_) | ShapeKind::Opaque => false,
86 }
87}