#arceos #macro #api

macro no-std crate_interface

Provides a way to define an interface (trait) in a crate, but can implement or use it in any crate

5 releases

new 0.1.4 Jan 18, 2025
0.1.3 Jul 30, 2024
0.1.2 Jul 11, 2024
0.1.1 May 3, 2023
0.1.0 May 3, 2023

#1934 in Procedural macros

Download history 171/week @ 2024-09-30 754/week @ 2024-10-07 1597/week @ 2024-10-14 1062/week @ 2024-10-21 582/week @ 2024-10-28 108/week @ 2024-11-04 455/week @ 2024-11-11 753/week @ 2024-11-18 543/week @ 2024-11-25 625/week @ 2024-12-02 457/week @ 2024-12-09 577/week @ 2024-12-16 744/week @ 2024-12-23 710/week @ 2024-12-30 752/week @ 2025-01-06 676/week @ 2025-01-13

2,908 downloads per month
Used in 3 crates (via kernel_guard)

GPL-3.0-or-later OR Apache-2…

12KB
163 lines

crate_interface

Crates.io Docs.rs CI

Provides a way to define an interface (trait) in a crate, but can implement or use it in any crate. It 's usually used to solve the problem of circular dependencies between crates.

Example

// Define the interface
#[crate_interface::def_interface]
pub trait HelloIf {
    fn hello(&self, name: &str, id: usize) -> String;
}

// Implement the interface in any crate
struct HelloIfImpl;

#[crate_interface::impl_interface]
impl HelloIf for HelloIfImpl {
    fn hello(&self, name: &str, id: usize) -> String {
        format!("Hello, {} {}!", name, id)
    }
}

// Call `HelloIfImpl::hello` in any crate
use crate_interface::call_interface;
assert_eq!(
    call_interface!(HelloIf::hello("world", 123)),
    "Hello, world 123!"
);
assert_eq!(
    call_interface!(HelloIf::hello, "rust", 456), // another calling style
    "Hello, rust 456!"
);

Implementation

The procedural macros in the above example will generate the following code:

// #[def_interface]
pub trait HelloIf {
    fn hello(&self, name: &str, id: usize) -> String;
}

#[allow(non_snake_case)]
pub mod __HelloIf_mod {
    use super::*;
    extern "Rust" {
        pub fn __HelloIf_hello(name: &str, id: usize) -> String;
    }
}

struct HelloIfImpl;

// #[impl_interface]
impl HelloIf for HelloIfImpl {
    #[inline]
    fn hello(&self, name: &str, id: usize) -> String {
        {
            #[inline]
            #[export_name = "__HelloIf_hello"]
            extern "Rust" fn __HelloIf_hello(name: &str, id: usize) -> String {
                let _impl: HelloIfImpl = HelloIfImpl;
                _impl.hello(name, id)
            }
        }
        {
            format!("Hello, {} {}!", name, id)
        }
    }
}

// call_interface!
assert_eq!(
    unsafe { __HelloIf_mod::__HelloIf_hello("world", 123) },
    "Hello, world 123!"
);

Dependencies

~210–650KB
~15K SLoC