From 78a25a73bd7660c2a229f9e17885855e358c5813 Mon Sep 17 00:00:00 2001 From: Zeeshan Ali Khan Date: Sat, 7 Feb 2026 19:15:15 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=9A=A9=20core:=20Feature-gate=20std-o?= =?UTF-8?q?nly=20introspect=20Type=20impls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gate the following Type implementations behind `#[cfg(feature = "std")]`: - collections: HashMap, HashSet (not available in alloc) - special: Instant, SystemTime, PathBuf, Path, OsString, OsStr - wrappers: Rc, Arc, Cow This allows the introspection feature to work in no_std environments, with only these std-specific type implementations unavailable. Co-Authored-By: Claude Opus 4.5 --- zlink-core/src/introspect/type/collections.rs | 11 ++++++++++- zlink-core/src/introspect/type/primitives.rs | 2 ++ zlink-core/src/introspect/type/special.rs | 6 ++++++ zlink-core/src/introspect/type/wrappers.rs | 13 ++++++++++--- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/zlink-core/src/introspect/type/collections.rs b/zlink-core/src/introspect/type/collections.rs index 58073c5a..ed9f79e4 100644 --- a/zlink-core/src/introspect/type/collections.rs +++ b/zlink-core/src/introspect/type/collections.rs @@ -1,8 +1,14 @@ //! Type implementations for collection types. +use alloc::{ + collections::{BTreeMap, BTreeSet}, + string::String, + vec::Vec, +}; + use super::Type; use crate::{idl, idl::TypeRef}; -use alloc::collections::{BTreeMap, BTreeSet}; +#[cfg(feature = "std")] use std::collections::{HashMap, HashSet}; // ============================================================================ @@ -23,10 +29,12 @@ impl Type for &[T] { // Map types - Varlink maps always have string keys // ============================================================================ +#[cfg(feature = "std")] impl Type for HashMap { const TYPE: &'static idl::Type<'static> = &idl::Type::Map(TypeRef::new(V::TYPE)); } +#[cfg(feature = "std")] impl Type for HashMap<&str, V> { const TYPE: &'static idl::Type<'static> = &idl::Type::Map(TypeRef::new(V::TYPE)); } @@ -43,6 +51,7 @@ impl Type for BTreeMap<&str, V> { // Set types - represented as arrays in Varlink // ============================================================================ +#[cfg(feature = "std")] impl Type for HashSet { const TYPE: &'static idl::Type<'static> = &idl::Type::Array(TypeRef::new(T::TYPE)); } diff --git a/zlink-core/src/introspect/type/primitives.rs b/zlink-core/src/introspect/type/primitives.rs index efa3a8af..b667c26b 100644 --- a/zlink-core/src/introspect/type/primitives.rs +++ b/zlink-core/src/introspect/type/primitives.rs @@ -1,5 +1,7 @@ //! Type implementations for primitive types. +use alloc::string::String; + use super::Type; use crate::idl; diff --git a/zlink-core/src/introspect/type/special.rs b/zlink-core/src/introspect/type/special.rs index 407f93f8..9add8132 100644 --- a/zlink-core/src/introspect/type/special.rs +++ b/zlink-core/src/introspect/type/special.rs @@ -33,10 +33,12 @@ impl Type for core::time::Duration { const TYPE: &'static idl::Type<'static> = &idl::Type::Float; } +#[cfg(feature = "std")] impl Type for std::time::Instant { const TYPE: &'static idl::Type<'static> = &idl::Type::Float; } +#[cfg(feature = "std")] impl Type for std::time::SystemTime { const TYPE: &'static idl::Type<'static> = &idl::Type::Float; } @@ -45,10 +47,12 @@ impl Type for std::time::SystemTime { // Path types // ============================================================================ +#[cfg(feature = "std")] impl Type for std::path::PathBuf { const TYPE: &'static idl::Type<'static> = &idl::Type::String; } +#[cfg(feature = "std")] impl Type for std::path::Path { const TYPE: &'static idl::Type<'static> = &idl::Type::String; } @@ -57,10 +61,12 @@ impl Type for std::path::Path { // OS string types // ============================================================================ +#[cfg(feature = "std")] impl Type for std::ffi::OsString { const TYPE: &'static idl::Type<'static> = &idl::Type::String; } +#[cfg(feature = "std")] impl Type for std::ffi::OsStr { const TYPE: &'static idl::Type<'static> = &idl::Type::String; } diff --git a/zlink-core/src/introspect/type/wrappers.rs b/zlink-core/src/introspect/type/wrappers.rs index 0aa483b1..d8c1cd43 100644 --- a/zlink-core/src/introspect/type/wrappers.rs +++ b/zlink-core/src/introspect/type/wrappers.rs @@ -3,6 +3,13 @@ //! This module contains implementations for types that transparently wrap other types, //! such as smart pointers, cells, and optional types. +use alloc::{ + borrow::{Cow, ToOwned}, + boxed::Box, + rc::Rc, + sync::Arc, +}; + use super::Type; use crate::{idl, idl::TypeRef}; @@ -22,11 +29,11 @@ impl Type for Box { const TYPE: &'static idl::Type<'static> = T::TYPE; } -impl Type for std::rc::Rc { +impl Type for Rc { const TYPE: &'static idl::Type<'static> = T::TYPE; } -impl Type for std::sync::Arc { +impl Type for Arc { const TYPE: &'static idl::Type<'static> = T::TYPE; } @@ -46,6 +53,6 @@ impl Type for core::cell::RefCell { // Cow type - transparent wrapper // ============================================================================ -impl Type for std::borrow::Cow<'_, T> { +impl Type for Cow<'_, T> { const TYPE: &'static idl::Type<'static> = T::TYPE; } From 51aeca8681546f871eb73834cc070e62bc5fca11 Mon Sep 17 00:00:00 2001 From: Zeeshan Ali Khan Date: Sat, 7 Feb 2026 19:16:10 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=9A=A9=20core,tokio,smol:=20Remove=20?= =?UTF-8?q?std=20requirement=20from=20introspection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove `std` from `introspection` feature in zlink-core - Remove `introspection` from `service` feature in all crates The introspection feature no longer requires std since std-only Type implementations are now feature-gated. The service feature no longer pulls in introspection, allowing service to work in no_std environments. Co-Authored-By: Claude Opus 4.5 --- zlink-core/Cargo.toml | 4 ++-- zlink-smol/Cargo.toml | 2 +- zlink-tokio/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zlink-core/Cargo.toml b/zlink-core/Cargo.toml index e55c03f8..76e3b961 100644 --- a/zlink-core/Cargo.toml +++ b/zlink-core/Cargo.toml @@ -13,11 +13,11 @@ default = ["std", "server", "proxy", "tracing"] std = ["dep:rustix", "dep:libc", "zlink-macros/std"] server = [] proxy = ["zlink-macros/proxy"] -service = ["server", "zlink-macros/service", "introspection"] +service = ["server", "zlink-macros/service"] # IDL and introspection support idl = [] idl-parse = ["idl", "dep:winnow", "zlink-macros/idl-parse"] -introspection = ["std", "idl", "zlink-macros/introspection"] +introspection = ["idl", "zlink-macros/introspection"] [dependencies] serde = { version = "1.0.218", default-features = false, features = ["derive", "alloc"] } diff --git a/zlink-smol/Cargo.toml b/zlink-smol/Cargo.toml index 5f9c69bf..e09cd00c 100644 --- a/zlink-smol/Cargo.toml +++ b/zlink-smol/Cargo.toml @@ -12,7 +12,7 @@ authors.workspace = true default = ["service", "proxy", "tracing"] server = ["zlink-core/server"] proxy = ["zlink-core/proxy"] -service = ["server", "introspection", "zlink-core/service"] +service = ["server", "zlink-core/service"] idl = ["zlink-core/idl"] idl-parse = ["zlink-core/idl-parse"] introspection = ["zlink-core/introspection"] diff --git a/zlink-tokio/Cargo.toml b/zlink-tokio/Cargo.toml index 83122033..e9c3901d 100644 --- a/zlink-tokio/Cargo.toml +++ b/zlink-tokio/Cargo.toml @@ -12,7 +12,7 @@ authors.workspace = true default = ["service", "proxy", "tracing"] server = ["zlink-core/server"] proxy = ["zlink-core/proxy"] -service = ["server", "introspection", "zlink-core/service"] +service = ["server", "zlink-core/service"] idl = ["zlink-core/idl"] idl-parse = ["zlink-core/idl-parse"] introspection = ["zlink-core/introspection"] From 44c7f4d075ea592b5d074dcada5e9448863d0c98 Mon Sep 17 00:00:00 2001 From: Zeeshan Ali Khan Date: Sat, 7 Feb 2026 19:16:46 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=9A=A9=20macros:=20Reject=20FD=20attr?= =?UTF-8?q?ibutes=20in=20service=20macro=20without=20std?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add compile-time validation that rejects `#[zlink(fds)]` and `#[zlink(return_fds)]` attributes when the `std` feature is disabled. FD passing requires Unix file descriptors which are only available with std, so these attributes should produce a clear error message in no_std environments rather than failing later with confusing errors. Co-Authored-By: Claude Opus 4.5 --- zlink-macros/src/service/method.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/zlink-macros/src/service/method.rs b/zlink-macros/src/service/method.rs index 4193d4ba..2b7c3f87 100644 --- a/zlink-macros/src/service/method.rs +++ b/zlink-macros/src/service/method.rs @@ -112,6 +112,14 @@ impl MethodInfo { "at most one `#[zlink(fds)]` parameter is allowed per method", )); } + #[cfg(not(feature = "std"))] + if !fds_params.is_empty() || return_fds { + return Err(Error::new_spanned( + &method.sig, + "FD-related attributes (`#[zlink(fds)]` and `#[zlink(return_fds)]`) \ + require the `std` feature to be enabled", + )); + } // Extract return type and check if it's a Result or Stream. let (