chore: 将工具链更新到2024-07-23 (#864)

* chore: 将工具链更新到2024-07-23
This commit is contained in:
LoGin
2024-07-25 00:55:02 +08:00
committed by GitHub
parent 634349e0eb
commit bd70d2d1f4
150 changed files with 237 additions and 200 deletions

View File

@ -21,7 +21,7 @@ ifeq ($(ARCH), x86_64)
endif
endif
RUSTFLAGS = $(RUSTFLAGS_UNWIND)
RUSTFLAGS += $(RUSTFLAGS_UNWIND)
CFLAGS = $(GLOBAL_CFLAGS) -fno-pie $(CFLAGS_UNWIND) -I $(shell pwd) -I $(shell pwd)/include
@ -40,7 +40,7 @@ kernel_subdirs := common driver debug syscall libs
kernel_rust:
RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2023-08-15 $(CARGO_ZBUILD) build --release --target $(TARGET_JSON)
RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2024-07-23 $(CARGO_ZBUILD) build --release --target $(TARGET_JSON)
all: kernel

View File

@ -1,4 +1,5 @@
/// 每个架构都需要实现的IO接口
#[allow(unused)]
pub trait PortIOArch {
unsafe fn in8(port: u16) -> u8;
unsafe fn in16(port: u16) -> u16;

View File

@ -156,6 +156,7 @@ impl LocalApicTimerIntrController {
local_apic_timer.start_current();
}
#[allow(dead_code)]
pub(super) fn disable(&self) {
let cpu_id = smp_get_processor_id();
let local_apic_timer = local_apic_timer_instance_mut(cpu_id);

View File

@ -179,6 +179,7 @@ bitflags! {
}
}
#[allow(dead_code)]
pub(super) fn irq_msi_compose_msg(cfg: &HardwareIrqConfig, msg: &mut MsiMsg, dmar: bool) {
*msg = MsiMsg::new_zeroed();

View File

@ -35,6 +35,7 @@ extern "C" {
}
#[no_mangle]
#[allow(static_mut_refs)]
unsafe extern "C" fn kernel_main(
mb2_info: u64,
mb2_magic: u64,
@ -66,6 +67,7 @@ unsafe extern "C" fn kernel_main(
/// 在内存管理初始化之前的架构相关的早期初始化
#[inline(never)]
#[allow(static_mut_refs)]
pub fn early_setup_arch() -> Result<(), SystemError> {
let stack_start = unsafe { *(head_stack_start as *const u64) } as usize;
debug!("head_stack_start={:#x}\n", stack_start);

View File

@ -564,6 +564,7 @@ pub unsafe fn set_system_trap_gate(irq: u32, ist: u8, vaddr: VirtAddr) {
set_gate(idt_entry, 0xEF, ist, vaddr);
}
#[allow(static_mut_refs)]
unsafe fn get_idt_entry(irq: u32) -> &'static mut [u64] {
assert!(irq < 256);
let mut idt_vaddr =

View File

@ -26,6 +26,7 @@ pub struct X86MsiDataNormal {
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct X86MsiDataDmar {
pub dmar_subhandle: u32,
}

View File

@ -396,6 +396,7 @@ impl SigContext {
}
}
/// @brief 信号处理备用栈的信息
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct SigStack {
pub sp: *mut c_void,

View File

@ -42,6 +42,7 @@ pub struct MSRBitmap {
pub data: [u8; PAGE_SIZE],
}
#[allow(dead_code)]
#[derive(Debug)]
pub struct VcpuData {
/// The virtual and physical address of the Vmxon naturally aligned 4-KByte region of memory
@ -73,6 +74,7 @@ pub enum VcpuState {
Act = 2,
}
#[allow(dead_code)]
#[derive(Debug)]
pub struct VmxVcpu {
pub vcpu_id: u32,
@ -318,13 +320,13 @@ impl VmxVcpu {
)?;
vmx_vmwrite(
VmcsFields::HOST_GDTR_BASE as u32,
pseudo_descriptpr.base.to_bits() as u64,
pseudo_descriptpr.base as usize as u64,
)?;
vmx_vmwrite(VmcsFields::HOST_IDTR_BASE as u32, unsafe {
let mut pseudo_descriptpr: x86::dtables::DescriptorTablePointer<u64> =
Default::default();
x86::dtables::sidt(&mut pseudo_descriptpr);
pseudo_descriptpr.base.to_bits() as u64
pseudo_descriptpr.base as usize as u64
})?;
// fast entry into the kernel

View File

@ -64,10 +64,10 @@ pub fn vmx_vmlaunch() -> Result<(), SystemError> {
"push rsi",
"push rdi",
"vmwrite {0:r}, rsp",
"lea rax, 1f[rip]",
"lea rax, 2f[rip]",
"vmwrite {1:r}, rax",
"vmlaunch",
"1:",
"2:",
"pop rdi",
"pop rsi",
"pop rdx",

View File

@ -30,6 +30,7 @@ pub use interrupt::X86_64InterruptArch as CurrentIrqArch;
pub use crate::arch::asm::pio::X86_64PortIOArch as CurrentPortIOArch;
pub use kvm::X86_64KVMArch as KVMArch;
#[allow(unused_imports)]
pub use crate::arch::ipc::signal::X86_64SignalArch as CurrentSignalArch;
pub use crate::arch::time::X86_64TimeArch as CurrentTimeArch;

View File

@ -42,9 +42,8 @@ impl KernelThreadMechanism {
frame.rip = kernel_thread_bootstrap_stage1 as usize as u64;
// fork失败的话子线程不会执行。否则将导致内存安全问题。
let pid = ProcessManager::fork(&frame, clone_flags).map_err(|e| {
let pid = ProcessManager::fork(&frame, clone_flags).inspect_err(|_e| {
unsafe { KernelThreadCreateInfo::parse_unsafe_arc_ptr(create_info) };
e
})?;
ProcessManager::find(pid)

View File

@ -59,6 +59,7 @@ impl TSSManager {
x86::task::load_tr(selector);
}
#[allow(static_mut_refs)]
unsafe fn set_tss_descriptor(index: u16, vaddr: VirtAddr) {
const LIMIT: u64 = 103;
let gdt_vaddr = VirtAddr::new(&GDT_Table as *const _ as usize);

View File

@ -259,6 +259,7 @@ impl X86_64SMPArch {
}
impl SmpCpuManager {
#[allow(static_mut_refs)]
pub fn arch_init(_boot_cpu: ProcessorId) {
assert!(smp_get_processor_id().data() == 0);
// 写入APU_START_CR3这个值会在AP处理器启动时设置到CR3寄存器

View File

@ -1,6 +1,6 @@
{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",

View File

@ -111,6 +111,7 @@ impl Bus for AcpiBus {
///
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/acpi/acpi_bus.h#364
#[allow(unused)]
pub trait AcpiDevice: Device {}
/// Acpi驱动应当实现的trait
@ -120,4 +121,5 @@ pub trait AcpiDevice: Device {}
/// todo: 仿照linux的acpi_driver去设计这个trait
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/acpi/acpi_bus.h#163
#[allow(unused)]
pub trait AcpiDriver: Driver {}

View File

@ -478,9 +478,8 @@ impl BusManager {
driver_manager()
.create_attr_file(driver, &DriverAttrBind)
.map_err(|e| {
.inspect_err(|_e| {
driver_manager().remove_attr_file(driver, &DriverAttrUnbind);
e
})?;
return Ok(());

View File

@ -142,6 +142,7 @@ impl DeviceManager {
/// - Ok(true): 匹配成功
/// - Ok(false): 没有匹配成功
/// - Err(SystemError): 匹配过程中出现意外错误,没有匹配成功
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#899
fn do_device_attach_driver(
&self,
@ -484,17 +485,15 @@ impl DriverManager {
sysfs_instance()
.create_link(Some(&device_kobj), &driver_kobj, "driver".to_string())
.map_err(|e| {
.inspect_err(|_e| {
fail_rm_dev_link();
e
})?;
device_manager()
.create_file(device, &DeviceAttrCoredump)
.map_err(|e| {
.inspect_err(|_e| {
sysfs_instance().remove_link(&device_kobj, "driver".to_string());
fail_rm_dev_link();
e
})?;
return Ok(());

View File

@ -213,10 +213,10 @@ impl DriverManager {
bus_manager().add_driver(&driver)?;
self.add_groups(&driver, driver.groups()).map_err(|e| {
bus_manager().remove_driver(&driver);
e
})?;
self.add_groups(&driver, driver.groups())
.inspect_err(|_e| {
bus_manager().remove_driver(&driver);
})?;
// todo: 发送uevent

View File

@ -646,18 +646,16 @@ impl DeviceManager {
let parent_kobj = parent.clone() as Arc<dyn KObject>;
sysfs_instance()
.create_link(Some(&dev_kobj), &parent_kobj, "device".to_string())
.map_err(|e| {
.inspect_err(|_e| {
err_remove_subsystem(&dev_kobj);
e
})?;
}
sysfs_instance()
.create_link(Some(&subsys_kobj), &dev_kobj, dev.name())
.map_err(|e| {
.inspect_err(|_e| {
err_remove_device(&dev_kobj);
err_remove_subsystem(&dev_kobj);
e
})?;
return Ok(());
@ -695,18 +693,16 @@ impl DeviceManager {
// 添加kobj_type的属性文件
if let Some(kobj_type) = dev.kobj_type() {
self.add_groups(dev, kobj_type.attribute_groups().unwrap_or(&[]))
.map_err(|e| {
.inspect_err(|_e| {
err_remove_class_groups(dev);
e
})?;
}
// 添加设备本身的属性文件
self.add_groups(dev, dev.attribute_groups().unwrap_or(&[]))
.map_err(|e| {
.inspect_err(|_e| {
err_remove_kobj_type_groups(dev);
err_remove_class_groups(dev);
e
})?;
return Ok(());

View File

@ -64,6 +64,7 @@ pub trait PlatformDevice: Device {
/// @brief: 判断设备是否初始化
/// @parameter: None
/// @return: 如果已经初始化返回true否则返回false
#[allow(dead_code)]
fn is_initialized(&self) -> bool;
/// @brief: 设置设备状态

View File

@ -16,6 +16,7 @@ use super::{platform_bus, platform_device::PlatformDevice};
///
/// 应当在所有实现这个trait的结构体上方添加 `#[cast_to([sync] PlatformDriver)]`
/// 否则运行时将报错“该对象不是PlatformDriver”
#[allow(dead_code)]
pub trait PlatformDriver: Driver {
/// 检测设备是否能绑定到这个驱动
///

View File

@ -16,6 +16,7 @@ static mut CMAPPER: Option<LockedCacheMapper> = None;
/// 该结构体向外提供BlockCache服务
pub struct BlockCache;
#[allow(static_mut_refs)]
unsafe fn mapper() -> Result<&'static mut LockedCacheMapper, BlockCacheError> {
unsafe {
match &mut CMAPPER {
@ -25,6 +26,7 @@ unsafe fn mapper() -> Result<&'static mut LockedCacheMapper, BlockCacheError> {
};
}
#[allow(static_mut_refs)]
unsafe fn space() -> Result<&'static mut LockedCacheSpace, BlockCacheError> {
unsafe {
match &mut CSPACE {

View File

@ -195,9 +195,8 @@ impl AhciDisk {
return Err(SystemError::EIO);
}
}
if kbuf.is_some() {
buf.copy_from_slice(kbuf.as_ref().unwrap());
if let Some(kbuf) = &kbuf {
buf.copy_from_slice(kbuf);
}
compiler_fence(Ordering::SeqCst);

View File

@ -43,6 +43,7 @@ pub enum HbaPortType {
/// 声明了 HBA 的所有属性
#[repr(packed)]
#[allow(dead_code)]
pub struct HbaPort {
pub clb: u64, // 0x00, command list base address, 1K-byte aligned
pub fb: u64, // 0x08, FIS base address, 256-byte aligned
@ -65,6 +66,7 @@ pub struct HbaPort {
/// 全称 HBA Memory Register是HBA的寄存器在内存中的映射
#[repr(packed)]
#[allow(dead_code)]
pub struct HbaMem {
pub cap: u32, // 0x00, Host capability
pub ghc: u32, // 0x04, Global host control
@ -94,6 +96,7 @@ pub struct HbaPrdtEntry {
/// HAB Command Table
/// 每个 Port 一个 Table主机和设备的交互都靠这个数据结构
#[repr(packed)]
#[allow(dead_code)]
pub struct HbaCmdTable {
// 0x00
pub cfis: [u8; 64], // Command FIS
@ -262,6 +265,7 @@ pub enum FisType {
}
#[repr(packed)]
#[allow(dead_code)]
pub struct FisRegH2D {
// DWORD 0
pub fis_type: u8, // FIS_TYPE_REG_H2D

View File

@ -168,9 +168,8 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
let st_ptr = st_vaddr.data() as *const uefi_raw::table::system::SystemTable;
efi_manager()
.check_system_table_header(unsafe { &st_ptr.as_ref().unwrap().header }, 2)
.map_err(|e| {
.inspect_err(|_| {
err_unmap_systable(st_vaddr);
e
})?;
let st_ref = unsafe { st_ptr.as_ref().unwrap() };

View File

@ -1,4 +1,5 @@
use crate::driver::{base::device::Device, input::serio::serio_device::SerioDevice};
// todo: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/libps2.h#33
#[allow(unused)]
pub trait Ps2Device: Device + SerioDevice {}

View File

@ -387,6 +387,7 @@ impl Ps2MouseDevice {
Ok(())
}
#[allow(dead_code)]
fn wait_for_read(&self) -> Result<(), SystemError> {
let timeout = 100_000;
for _ in 0..timeout {

View File

@ -47,14 +47,16 @@ pub fn i8042_init() -> Result<(), SystemError> {
Ok(())
}
// TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#441
/// TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#441
#[allow(dead_code)]
pub fn i8042_start(_serio: &Arc<dyn SerioDevice>) -> Result<(), SystemError> {
todo!()
todo!("i8042_start")
}
// TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#471
/// TODO: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/i8042.c#471
#[allow(dead_code)]
pub fn i8042_stop(_serio: &Arc<dyn SerioDevice>) -> Result<(), SystemError> {
todo!()
todo!("i8042_stop")
}
/// # 函数的功能

View File

@ -8,6 +8,7 @@ use super::serio_bus;
/// 串行设备实现该trait的设备实例挂载在serio总线上同时应该实现Device trait
///
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serio.h#20
#[allow(dead_code)]
pub trait SerioDevice: Device {
/// # 函数功能
///

View File

@ -11,6 +11,7 @@ use super::{serio_bus, serio_device::SerioDevice};
/// 实现该trait的设备驱动实例应挂载在serio总线上同时应该实现Driver trait
///
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serio.h#67
#[allow(dead_code)]
pub trait SerioDriver: Driver {
// 写入时唤醒设备
fn write_wakeup(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;

View File

@ -780,7 +780,8 @@ const E1000E_TXD_CMD_EOP: u8 = 1 << 0;
const E1000E_TXD_CMD_IFCS: u8 = 1 << 1;
const E1000E_TXD_CMD_RS: u8 = 1 << 3;
// E1000E驱动初始化过程中可能的错误
/// E1000E驱动初始化过程中可能的错误
#[allow(dead_code)]
pub enum E1000EPciError {
// 获取到错误类型的BARIO BAR
// An IO BAR was provided rather than a memory BAR.

View File

@ -15,7 +15,6 @@ use alloc::sync::{Arc, Weak};
use alloc::vec::Vec;
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use log::debug;
use smoltcp::wire::HardwareAddress;
use smoltcp::{
phy::{self},

View File

@ -13,7 +13,7 @@ pub mod e1000e;
pub mod irq_handle;
pub mod loopback;
pub mod virtio_net;
#[allow(dead_code)]
pub trait NetDevice: Device {
/// @brief 获取网卡的MAC地址
fn mac(&self) -> EthernetAddress;

View File

@ -468,8 +468,7 @@ fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize)
1 => {
return (
u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap())
.try_into()
.unwrap(),
.into(),
next_base_index,
);
}

View File

@ -12,6 +12,7 @@ use super::{dev_id::PciDeviceID, device::PciDevice, subsys::pci_bus};
/// Pci驱动应该实现的trait
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/pci.h#907
#[allow(dead_code)]
pub trait PciDriver: Driver {
/// # 函数的功能
/// 对设备进行probe操作

View File

@ -47,6 +47,7 @@ pub trait RtcDevice: Device {
fn class_ops(&self) -> &'static dyn RtcClassOps;
}
#[allow(dead_code)]
pub trait RtcClassOps: Send + Sync + Debug {
fn read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError>;
fn set_time(&self, dev: &Arc<dyn RtcDevice>, time: &RtcTime) -> Result<(), SystemError>;

View File

@ -9,6 +9,7 @@ use self::serial8250::serial8250_manager;
pub mod serial8250;
#[allow(dead_code)]
pub trait UartDriver: Debug + Send + Sync {
fn device_number(&self) -> DeviceNumber;
@ -21,6 +22,7 @@ pub trait UartDriver: Debug + Send + Sync {
/// 串口端口应当实现的trait
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serial_core.h#428
#[allow(dead_code)]
pub trait UartPort {
fn iobase(&self) -> Option<usize> {
None

View File

@ -141,6 +141,7 @@ impl Serial8250Manager {
}
/// 所有的8250串口设备都应该实现的trait
#[allow(dead_code)]
trait Serial8250Port: UartPort {
fn device(&self) -> Option<Arc<Serial8250ISADevices>> {
None

View File

@ -20,6 +20,7 @@ static mut PIO_PORTS: [Option<Serial8250PIOPort>; 8] =
[None, None, None, None, None, None, None, None];
impl Serial8250Manager {
#[allow(static_mut_refs)]
pub(super) fn bind_pio_ports(
&self,
uart_driver: &Arc<Serial8250ISADriver>,
@ -251,6 +252,7 @@ impl Serial8250PIOPortInner {
Self { device: None }
}
#[allow(dead_code)]
pub fn device(&self) -> Option<Arc<Serial8250ISADevices>> {
if let Some(device) = self.device.as_ref() {
return device.upgrade();

View File

@ -10,6 +10,7 @@ pub trait ConsoleSwitch: Sync + Send {
fn con_init(&self, vc_data: &mut VirtualConsoleData, init: bool) -> Result<(), SystemError>;
/// 进行释放等系列操作,目前未使用
#[allow(dead_code)]
fn con_deinit(&self) -> Result<(), SystemError>;
/// ## 清空console的一片区域

View File

@ -7,7 +7,6 @@ use alloc::{
collections::LinkedList,
string::String,
sync::{Arc, Weak},
vec::Vec,
};
use system_error::SystemError;
@ -277,14 +276,6 @@ pub struct TtyContorlInfo {
pub packet: bool,
}
#[derive(Debug, Default)]
pub struct TtyCoreWriteData {
/// 写缓冲区
pub write_buf: Vec<u8>,
/// 写入数量
pub write_cnt: usize,
}
#[derive(Debug, Default)]
pub struct TtyFlowState {
/// 表示流控是否被停止
@ -465,9 +456,6 @@ impl TtyCoreData {
}
}
/// TTY 核心接口不同的tty需要各自实现这个trait
pub trait TtyCoreFuncs: Debug + Send + Sync {}
impl TtyOperation for TtyCore {
#[inline]
fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {

View File

@ -1344,7 +1344,7 @@ impl NTtyData {
tty.write(core, &[8], 1)?;
}
if tty.put_char(tty.core(), b' ').is_err() {
tty.write(core, &[b' '], 1)?;
tty.write(core, b" ", 1)?;
}
self.cursor_column -= 1;
space -= 1;
@ -1357,7 +1357,7 @@ impl NTtyData {
}
if tty.put_char(tty.core(), b'^').is_err() {
tty.write(core, &[b'^'], 1)?;
tty.write(core, b"^", 1)?;
}
if tty.put_char(tty.core(), ch ^ 0o100).is_err() {

View File

@ -132,7 +132,6 @@ pub struct VirtualConsoleData {
pub utf_char: u32,
/// 构建utf时需要的参数表示目前接收了多少个字节的数据来构建utf字符
pub npar: u32,
///
pub par: [u32; NPAR],
/// 字符转换表 用于将输入字符映射到特定的字符
@ -1786,6 +1785,7 @@ impl VirtualConsoleData {
draw.size = 0;
}
#[allow(clippy::manual_rotate)]
fn build_attr(
&self,
color: u8,

View File

@ -341,12 +341,12 @@ impl Attribute for AttrCursorBlink {
}
#[derive(Debug, Default)]
#[allow(dead_code)]
pub struct FrameBufferConsoleData {
/// 光标闪烁间隔
pub cursor_blink_jiffies: i64,
/// 是否刷新光标
pub cursor_flash: bool,
///
pub display: FbConsoleDisplay,
/// 光标状态
pub cursor_state: FbCursor,

View File

@ -301,6 +301,7 @@ impl FrameBufferInfoData {
}
/// 帧缓冲区信息
#[allow(dead_code)]
pub trait FrameBufferInfo: FrameBufferOps {
fn framebuffer_info_data(&self) -> &RwLock<FrameBufferInfoData>;
@ -377,6 +378,7 @@ pub trait FrameBufferInfo: FrameBufferOps {
/// 帧缓冲区操作
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/fb.h#237
#[allow(dead_code)]
pub trait FrameBufferOps {
fn fb_open(&self, user: bool);
fn fb_release(&self, user: bool);
@ -1063,6 +1065,7 @@ pub enum FbAccel {
// Add other accelerators here
}
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub struct BootTimeScreenInfo {
pub origin_x: u8,

View File

@ -18,6 +18,7 @@ pub mod virtio_impl;
/// virtio 设备厂商ID
pub const VIRTIO_VENDOR_ID: u16 = 0x1af4;
#[allow(dead_code)]
pub trait VirtIODevice: Device {
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError>;

View File

@ -35,6 +35,7 @@ use super::{
};
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#506
#[allow(dead_code)]
pub trait IrqChip: Sync + Send + Any + Debug {
fn name(&self) -> &'static str;
/// start up the interrupt (defaults to ->enable if ENOSYS)
@ -127,6 +128,7 @@ pub trait IrqChip: Sync + Send + Any + Debug {
}
/// enable/disable power management wake-on of an interrupt
#[allow(dead_code)]
fn irq_set_wake(&self, _irq_data: &Arc<IrqData>, _on: bool) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
@ -281,6 +283,7 @@ struct InnerIrqChipGeneric {
chip_types: Vec<IrqChipType>,
}
#[allow(dead_code)]
pub trait IrqChipGenericOps: Debug + Send + Sync {
/// Alternate I/O accessor (defaults to readl if NULL)
unsafe fn reg_readl(&self, addr: VirtAddr) -> u32;

View File

@ -644,6 +644,7 @@ pub enum IrqDomainBusToken {
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#107
pub trait IrqDomainOps: Debug + Send + Sync {
/// 匹配一个中断控制器设备节点到一个主机。
#[allow(dead_code)]
fn match_node(
&self,
_irq_domain: &Arc<IrqDomain>,
@ -667,6 +668,7 @@ pub trait IrqDomainOps: Debug + Send + Sync {
}
/// 删除一个虚拟中断号与一个硬件中断号之间的映射。
#[allow(dead_code)]
fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber);
fn activate(

View File

@ -124,6 +124,7 @@ impl MsiDesc {
}
}
#[allow(dead_code)]
pub trait MsiDescFunc: Debug + Send + Sync {
/// Callback that may be called when the MSI message
/// address or data changes.

View File

@ -1328,6 +1328,7 @@ impl ShortDirEntry {
}
/// @brief 计算短目录项的名称的校验和
#[allow(clippy::manual_rotate)]
fn checksum(&self) -> u8 {
let mut result = 0;

View File

@ -45,6 +45,7 @@ pub const MAX_FILE_SIZE: u64 = 0xffff_ffff;
/// @brief 表示当前簇和上一个簇的关系的结构体
/// 定义这样一个结构体的原因是FAT文件系统的文件中前后两个簇具有关联关系。
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, Default)]
pub struct Cluster {
pub cluster_num: u64,
@ -642,7 +643,7 @@ impl FATFileSystem {
self.set_entry(cluster, FATEntry::Unused)?;
self.fs_info.0.lock().update_free_count_delta(1);
// 安全选项:清空被释放的簇
#[cfg(feature = "secure")]
#[cfg(feature = "fatfs-secure")]
self.zero_cluster(cluster)?;
return Ok(());
} else {

View File

@ -55,7 +55,7 @@ impl MbrDiskPartitionTableEntry {
#[repr(packed)]
#[derive(Debug, Clone, Copy)]
pub struct MbrDiskPartionTable {
pub reserved: [u8; 446],
pub _reserved: [u8; 446],
pub dpte: [MbrDiskPartitionTableEntry; 4], // 磁盘分区表项
pub bs_trailsig: u16,
}
@ -63,7 +63,7 @@ pub struct MbrDiskPartionTable {
impl Default for MbrDiskPartionTable {
fn default() -> Self {
MbrDiskPartionTable {
reserved: [0; 446],
_reserved: [0; 446],
dpte: [Default::default(); 4],
bs_trailsig: Default::default(),
}

View File

@ -1,5 +1,3 @@
use core::usize;
use system_error::SystemError;
use crate::syscall::Syscall;

View File

@ -25,6 +25,9 @@ use super::vfs::{
file::FilePrivateData, syscall::ModeType, utils::DName, FileSystem, FileSystemMaker, FsInfo,
IndexNode, InodeId, Metadata, SpecialNodeData,
};
use linkme::distributed_slice;
use super::vfs::{Magic, SuperBlock};
/// RamFS的inode名称的最大长度

View File

@ -136,9 +136,8 @@ impl SysFS {
if let Some(name) = group.name() {
parent_inode = inode
.find(name)
.map_err(|e| {
.inspect_err(|_e| {
warn!("sysfs group '{name}' not found for kobject {kobj:?}");
e
})?
.downcast_arc()
.unwrap();

View File

@ -160,25 +160,6 @@ impl MountFSInode {
}
}
/// 将新的挂载点-挂载文件系统添加到父级的挂载树
pub(super) fn do_mount(
&self,
inode_id: InodeId,
new_mount_fs: Arc<MountFS>,
) -> Result<(), SystemError> {
let mut guard = self.mount_fs.mountpoints.lock();
if guard.contains_key(&inode_id) {
return Err(SystemError::EBUSY);
}
guard.insert(inode_id, new_mount_fs);
return Ok(());
}
pub(super) fn inode_id(&self) -> InodeId {
self.metadata().map(|x| x.inode_id).unwrap()
}
fn do_find(&self, name: &str) -> Result<Arc<MountFSInode>, SystemError> {
// 直接调用当前inode所在的文件系统的find方法进行查找
// 由于向下查找可能会跨越文件系统的边界因此需要尝试替换inode

View File

@ -398,6 +398,7 @@ impl PosixOpenHow {
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct OpenHow {
pub o_flags: FileMode,
@ -1707,8 +1708,7 @@ impl IoVecs {
// 将用户空间的IoVec转换为引用注意这里的引用是静态的因为用户空间的IoVec不会被释放
let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt);
let mut slices: Vec<&mut [u8]> = vec![];
slices.reserve(iovs.len());
let mut slices: Vec<&mut [u8]> = Vec::with_capacity(iovs.len());
for iov in iovs.iter() {
if iov.iov_len == 0 {

View File

@ -1,8 +1,7 @@
use core::cmp::Ordering;
use core::fmt::Debug;
use core::fmt::{self, Debug};
use core::hash::Hash;
use alloc::string::ToString;
use alloc::{string::String, sync::Arc};
use system_error::SystemError;
@ -135,9 +134,9 @@ impl Clone for DName {
}
}
impl ToString for DName {
fn to_string(&self) -> String {
(*self.0).clone()
impl fmt::Display for DName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}

View File

@ -27,6 +27,7 @@ fn init_intertrait() {
#[derive(Debug)]
pub struct BootParams {
pub screen_info: BootTimeScreenInfo,
#[allow(dead_code)]
pub arch: ArchBootParams,
boot_command_line: [u8; Self::BOOT_COMMAND_LINE_SIZE],
}

View File

@ -64,6 +64,7 @@ pub struct SignalStruct {
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct InnerSignalStruct {
pub cnt: AtomicI64,
/// 如果对应linux这部分会有一个引用计数但是没发现在哪里有用到需要计算引用的地方因此

View File

@ -7,22 +7,20 @@
#![feature(const_for)]
#![feature(const_mut_refs)]
#![feature(const_trait_impl)]
#![feature(const_transmute_copy)]
#![feature(const_refs_to_cell)]
#![feature(core_intrinsics)]
#![feature(c_void_variant)]
#![feature(extract_if)]
#![feature(fn_align)]
#![feature(inline_const)]
#![feature(naked_functions)]
#![feature(new_uninit)]
#![feature(panic_info_message)]
#![feature(ptr_internals)]
#![feature(ptr_to_from_bits)]
#![feature(trait_upcasting)]
#![feature(slice_ptr_get)]
#![feature(sync_unsafe_cell)]
#![feature(vec_into_raw_parts)]
#![cfg_attr(target_os = "none", no_std)]
#![allow(internal_features)]
// clippy的配置
#![deny(clippy::all)]
#![allow(clippy::bad_bit_mask)]
@ -123,15 +121,7 @@ pub fn panic(info: &PanicInfo) -> ! {
println!("No location info");
}
}
match info.message() {
Some(msg) => {
println!("Message:\n\t{}", msg);
}
None => {
println!("No panic message.");
}
}
println!("Message:\n\t{}", info.message());
#[cfg(all(feature = "backtrace", target_arch = "x86_64"))]
{

View File

@ -1,15 +0,0 @@
/// @brief 由bindgen生成的结构体转换成rust原生定义的结构体的特性
pub trait FFIBind2Rust<T> {
/// 转换为不可变引用
fn convert_ref(src: *const T) -> Option<&'static Self>;
/// 转换为可变引用
fn convert_mut(src: *mut T) -> Option<&'static mut Self>;
}
pub fn __convert_mut<'a, S, D>(src: *mut S) -> Option<&'a mut D> {
return unsafe { core::mem::transmute::<*mut S, *mut D>(src).as_mut() };
}
pub fn __convert_ref<'a, S, D>(src: *const S) -> Option<&'a D> {
return unsafe { core::mem::transmute::<*const S, *const D>(src).as_ref() };
}

View File

@ -2,6 +2,7 @@ use self::font_type::vga8x16::FONT_VGA_8X16;
pub mod font_type;
#[allow(dead_code)]
pub struct FontDesc {
pub index: usize,
pub name: &'static str,

View File

@ -1,5 +1,6 @@
#![no_std]
#![feature(core_intrinsics)]
#![allow(internal_features)]
#![allow(clippy::needless_return)]
use core::intrinsics::unlikely;

View File

@ -1,18 +0,0 @@
# Cargo lock in subs
**/Cargo.lock
# Generated by Cargo
**/target/
**/*.rs.bk
**/*.iml
.idea/
.vscode/
/db/
/snapshot/
/log/
/keys/
/test/log/
# macOS
.DS_store

View File

@ -1,27 +0,0 @@
[package]
name = "intertrait"
version = "0.2.2"
authors = ["CodeChain Team <hi@codechain.io>"]
license = "GPLv2(for code modified by dragonos) MIT OR Apache-2.0"
description = "Allow for inter-trait casting"
edition = "2018"
repository = "https://github.com/CodeChain-io/intertrait"
documentation = "https://docs.rs/intertrait"
readme = "README.md"
categories = ["rust-patterns"]
keywords = ["trait", "cast", "any"]
include = ["src/**/*", "Cargo.toml", "LICENSE-*", "README.md"]
[dependencies]
linkme = "0.2"
hashbrown = "0.13.2"
intertrait-macros = { version = "=0.2.2", path = "macros" }
[target.'cfg(not(target_os = "none"))'.dependencies]
once_cell = "1.4"
[dev-dependencies]
trybuild = "1.0"
doc-comment = "0.3"

View File

@ -1,17 +0,0 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,163 +0,0 @@
# Intertrait
We forked this lib from [intertrait](https://github.com/CodeChain-io/intertrait/) (revision d5d6dcb), and modified it to support `no_std` environment.
## Notice
The modified version is licensed under GPLv2 and later, while the original version is licensed under MIT/Apache license.(Codes modified by us are licensed under GPLv2 and later.)
This library provides direct casting among trait objects implemented by a type.
In Rust, a trait object for a sub-trait of [`std::any::Any`] can be downcast to a concrete type at runtime
if the type is known. But no direct casting between two trait objects (i.e. without involving the concrete type
of the backing value) is possible (even no coercion from a trait object for a trait to that for its super-trait yet).
With this crate, any trait object for a sub-trait of [`CastFrom`] can be cast directly to a trait object
for another trait implemented by the underlying type if the target traits are registered beforehand
with the macros provided by this crate.
# Dependencies
Add the following two dependencies to your `Cargo.toml`:
```toml
[dependencies]
intertrait = "0.2"
linkme = "0.2"
```
The `linkme` dependency is required due to the use of `linkme` macro in the output of `intertrait` macros.
# Usage
```rust
use intertrait::*;
use intertrait::cast::*;
struct Data;
trait Source: CastFrom {}
trait Greet {
fn greet(&self);
}
#[cast_to]
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
impl Source for Data {}
fn main() {
let data = Data;
let source: &dyn Source = &data;
let greet = source.cast::<dyn Greet>();
greet.unwrap().greet();
}
```
Target traits must be explicitly designated beforehand. There are three ways of doing it:
### `#[cast_to]` to `impl` item
The trait implemented is designated as a target trait.
```rust
use intertrait::*;
struct Data;
trait Greet { fn greet(&self); }
#[cast_to]
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
```
### `#[cast_to(Trait)]` to type definition
For the type, the traits specified as arguments to the `#[cast_to(...)]` attribute are designated as target traits.
```rust
use intertrait::*;
trait Greet { fn greet(&self); }
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
#[cast_to(Greet, std::fmt::Debug)]
#[derive(std::fmt::Debug)]
struct Data;
```
### `castable_to!(Type => Trait1, Trait2)`
For the type, the traits following `:` are designated as target traits.
```rust
use intertrait::*;
#[derive(std::fmt::Debug)]
struct Data;
trait Greet { fn greet(&self); }
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
// Only in an item position due to the current limitation in the stable Rust.
// https://github.com/rust-lang/rust/pull/68717
castable_to!(Data => Greet, std::fmt::Debug);
fn main() {}
```
## `Arc` Support
`std::sync::Arc` is unique in that it implements `downcast` method only on `dyn Any + Send + Sync + 'static'.
To use with `Arc`, the following steps should be taken:
* Mark source traits with [`CastFromSync`] instead of [`CastFrom`]
* Add `[sync]` flag to `#[cast_to]` and `castable_to!` as follows:
```ignore
#[cast_to([sync])]
#[cast_to([sync] Trait1, Trait2)]
castable_to!(Type => [sync] Trait, Trait2);
```
# How it works
First of all, [`CastFrom`] trait makes it possible to retrieve an object of [`std::any::Any`]
from an object for a sub-trait of [`CastFrom`].
And the macros provided by `intertrait` generates trampoline functions for downcasting a trait object
for [`std::any::Any`] back to its concrete type and then creating a trait object for the target trait from it.
Those trampoline functions are aggregated into a global registry
using [`linkme`](https://github.com/dtolnay/linkme/) crate, which involves no (generally discouraged)
life-before-main trick. The registry is keyed with a pair of [`TypeId`]s, which are those of the concrete type
backing a trait object for a sub-trait of [`CastFrom`] and the target trait (the actual implementation
is a bit different here, but conceptually so).
In the course, it doesn't rely on any unstable Rust implementation details such as the layout of trait objects
that may be changed in the future.
# Credits
`intertrait` has taken much of its core ideas from the great [`traitcast`](https://github.com/bch29/traitcast) crate.
# License
The modified version is licensed under GPLv2 and later, while the original version is licensed under MIT/Apache license.(Codes modified by us are licensed under GPLv2 and later.)
Modified version(revision 0.2.0):
* GPLv2 and later (You can find the full text of the license in the root directory of this repository.)
Original version(revision d5d6dcb):
* Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

View File

@ -1,23 +0,0 @@
[package]
name = "intertrait-macros"
description = "Macros for intertrait crate, which allows for direct casting between trait objects"
version = "0.2.2"
authors = ["CodeChain Team <hi@codechain.io>"]
license = "GPLv2(for code modified by dragonos) MIT OR Apache-2.0"
edition = "2018"
repository = "https://github.com/CodeChain-io/intertrait"
include = ["src/**/*", "Cargo.toml", "LICENSE-*"]
[lib]
proc-macro = true
[dependencies]
hashbrown = "0.13.2"
proc-macro2 = "1.0"
syn = { version = "1.0", features = ["full"] }
quote = "1.0"
uuid = { version = "0.8", features = ["v4"] }
[dev-dependencies]
intertrait = { version = "=0.2.2", path = ".." }
linkme = "0.2"

View File

@ -1,176 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,17 +0,0 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,76 +0,0 @@
use hashbrown::HashSet;
use syn::bracketed;
use syn::parse::{Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
use syn::{Error, Ident, Path, Token, Type};
#[derive(Hash, PartialEq, Eq)]
pub enum Flag {
Sync,
}
impl Flag {
fn from(ident: &Ident) -> Result<Self> {
match ident.to_string().as_str() {
"sync" => Ok(Flag::Sync),
unknown => {
let msg = format!("Unknown flag: {}", unknown);
Err(Error::new_spanned(ident, msg))
}
}
}
}
pub struct Targets {
pub flags: HashSet<Flag>,
pub paths: Vec<Path>,
}
impl Parse for Targets {
fn parse(input: ParseStream) -> Result<Self> {
let mut flags = HashSet::new();
let mut paths = Vec::new();
if input.is_empty() {
return Ok(Targets { flags, paths });
}
if input.peek(syn::token::Bracket) {
let content;
bracketed!(content in input);
for ident in Punctuated::<Ident, Token![,]>::parse_terminated(&content)? {
if !flags.insert(Flag::from(&ident)?) {
let msg = format!("Duplicated flag: {}", ident);
return Err(Error::new_spanned(ident, msg));
}
}
}
if input.is_empty() {
return Ok(Targets { flags, paths });
}
paths = Punctuated::<Path, Token![,]>::parse_terminated(input)?
.into_iter()
.collect();
Ok(Targets { flags, paths })
}
}
pub struct Casts {
pub ty: Type,
pub targets: Targets,
}
impl Parse for Casts {
fn parse(input: ParseStream) -> Result<Self> {
let ty: Type = input.parse()?;
input.parse::<Token![=>]>()?;
Ok(Casts {
ty,
targets: input.parse()?,
})
}
}

View File

@ -1,64 +0,0 @@
use core::str::from_utf8_unchecked;
use proc_macro2::TokenStream;
use uuid::adapter::Simple;
use uuid::Uuid;
use quote::format_ident;
use quote::quote;
use quote::ToTokens;
pub fn generate_caster(ty: &impl ToTokens, trait_: &impl ToTokens, sync: bool) -> TokenStream {
let mut fn_buf = [0u8; FN_BUF_LEN];
let fn_ident = format_ident!("{}", new_fn_name(&mut fn_buf));
// 生成从dyn trait转换为具体类型结构体ty的caster
let new_caster = if sync {
quote! {
::intertrait::Caster::<dyn #trait_>::new_sync(
|from| from.downcast_ref::<#ty>().unwrap(),
|from| from.downcast_mut::<#ty>().unwrap(),
|from| from.downcast::<#ty>().unwrap(),
|from| from.downcast::<#ty>().unwrap(),
|from| from.downcast::<#ty>().unwrap()
)
}
} else {
quote! {
::intertrait::Caster::<dyn #trait_>::new(
|from| from.downcast_ref::<#ty>().unwrap(),
|from| from.downcast_mut::<#ty>().unwrap(),
|from| from.downcast::<#ty>().unwrap(),
|from| from.downcast::<#ty>().unwrap(),
)
}
};
// 由于过程宏是在预编译期执行的这里的target_os是linux。
// 编译完成的proc macro会交给下一阶段进行编译因此#[cfg(target_os)]会在下一阶段生效。
// 我们必须在预处理阶段把两种代码的token stream都生成出来然后在下一阶段选择性地使用其中一种。
quote! {
#[cfg(not(target_os = "none"))]
#[::linkme::distributed_slice(::intertrait::CASTERS)]
fn #fn_ident() -> (::std::any::TypeId, ::intertrait::BoxedCaster) {
(::std::any::TypeId::of::<#ty>(), Box::new(#new_caster))
}
#[cfg(target_os = "none")]
#[::linkme::distributed_slice(::intertrait::CASTERS)]
fn #fn_ident() -> (::core::any::TypeId, ::intertrait::BoxedCaster) {
(::core::any::TypeId::of::<#ty>(), alloc::boxed::Box::new(#new_caster))
}
}
}
const FN_PREFIX: &[u8] = b"__";
const FN_BUF_LEN: usize = FN_PREFIX.len() + Simple::LENGTH;
fn new_fn_name(buf: &mut [u8]) -> &str {
buf[..FN_PREFIX.len()].copy_from_slice(FN_PREFIX);
Uuid::new_v4()
.to_simple()
.encode_lower(&mut buf[FN_PREFIX.len()..]);
unsafe { from_utf8_unchecked(&buf[..FN_BUF_LEN]) }
}

View File

@ -1,82 +0,0 @@
use hashbrown::HashSet;
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::Token;
use syn::{
AngleBracketedGenericArguments, Binding, GenericArgument, ImplItem, ItemImpl, Path,
PathArguments,
};
use PathArguments::AngleBracketed;
use crate::args::Flag;
use crate::gen_caster::generate_caster;
pub fn process(flags: &HashSet<Flag>, input: ItemImpl) -> TokenStream {
let ItemImpl {
ref self_ty,
ref trait_,
ref items,
..
} = input;
let generated = match trait_ {
None => quote_spanned! {
self_ty.span() => compile_error!("#[cast_to] should only be on an impl of a trait");
},
Some(trait_) => match trait_ {
(Some(bang), _, _) => quote_spanned! {
bang.span() => compile_error!("#[cast_to] is not for !Trait impl");
},
(None, path, _) => {
let path = fully_bound_trait(path, items);
generate_caster(self_ty, &path, flags.contains(&Flag::Sync))
}
},
};
quote! {
#input
#generated
}
}
fn fully_bound_trait(path: &Path, items: &[ImplItem]) -> impl ToTokens {
let bindings = items
.iter()
.filter_map(|item| {
if let ImplItem::Type(assoc_ty) = item {
Some(GenericArgument::Binding(Binding {
ident: assoc_ty.ident.to_owned(),
eq_token: Default::default(),
ty: assoc_ty.ty.to_owned(),
}))
} else {
None
}
})
.collect::<Punctuated<_, Token![,]>>();
let mut path = path.clone();
if bindings.is_empty() {
return path;
}
if let Some(last) = path.segments.last_mut() {
match &mut last.arguments {
PathArguments::None => {
last.arguments = AngleBracketed(AngleBracketedGenericArguments {
colon2_token: None,
lt_token: Default::default(),
args: bindings,
gt_token: Default::default(),
})
}
AngleBracketed(args) => args.args.extend(bindings),
_ => {}
}
}
path
}

View File

@ -1,31 +0,0 @@
use hashbrown::HashSet;
use proc_macro2::TokenStream;
use syn::spanned::Spanned;
use syn::{DeriveInput, Path};
use quote::{quote, quote_spanned};
use crate::args::Flag;
use crate::gen_caster::generate_caster;
pub fn process(flags: &HashSet<Flag>, paths: Vec<Path>, input: DeriveInput) -> TokenStream {
let DeriveInput {
ref ident,
ref generics,
..
} = input;
let generated = if generics.lt_token.is_some() {
quote_spanned! {
generics.span() => compile_error!("#[cast_to(..)] can't be used on a generic type definition");
}
} else {
paths
.into_iter()
.flat_map(|t| generate_caster(ident, &t, flags.contains(&Flag::Sync)))
.collect()
};
quote! {
#input
#generated
}
}

View File

@ -1,145 +0,0 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use syn::{parse, parse_macro_input, DeriveInput, ItemImpl};
use args::{Casts, Flag, Targets};
use gen_caster::generate_caster;
mod args;
mod gen_caster;
mod item_impl;
mod item_type;
/// Attached on an `impl` item or type definition, registers traits as targets for casting.
///
/// If on an `impl` item, no argument is allowed. But on a type definition, the target traits
/// must be listed explicitly.
///
/// Add `[sync]` before the list of traits if the underlying type is `Sync + Send` and you
/// need `std::sync::Arc`.
///
/// # Examples
/// ## On a trait impl
/// ```
/// use intertrait::*;
///
/// struct Data;
///
/// trait Greet {
/// fn greet(&self);
/// }
///
/// // Greet can be cast into from any sub-trait of CastFrom implemented by Data.
/// #[cast_to]
/// impl Greet for Data {
/// fn greet(&self) {
/// println!("Hello");
/// }
/// }
/// ```
///
/// ## On a type definition
/// Use when a target trait is derived or implemented in an external crate.
/// ```
/// use intertrait::*;
///
/// // Debug can be cast into from any sub-trait of CastFrom implemented by Data
/// #[cast_to(std::fmt::Debug)]
/// #[derive(std::fmt::Debug)]
/// struct Data;
/// ```
///
/// ## For Arc
/// Use when the underlying type is `Sync + Send` and you want to use `Arc`.
/// ```
/// use intertrait::*;
///
/// // Debug can be cast into from any sub-trait of CastFrom implemented by Data
/// #[cast_to([sync] std::fmt::Debug)]
/// #[derive(std::fmt::Debug)]
/// struct Data;
/// ```
#[proc_macro_attribute]
pub fn cast_to(args: TokenStream, input: TokenStream) -> TokenStream {
match parse::<Targets>(args) {
Ok(Targets { flags, paths }) => {
if paths.is_empty() {
item_impl::process(&flags, parse_macro_input!(input as ItemImpl))
} else {
item_type::process(&flags, paths, parse_macro_input!(input as DeriveInput))
}
}
Err(err) => vec![err.to_compile_error(), input.into()]
.into_iter()
.collect(),
}
.into()
}
/// Declares target traits for casting implemented by a type.
///
/// This macro is for registering both a concrete type and its traits to be targets for casting.
/// Useful when the type definition and the trait implementations are in an external crate.
///
/// **Note**: this macro cannot be used in an expression or statement prior to Rust 1.45.0,
/// due to [a previous limitation](https://github.com/rust-lang/rust/pull/68717).
/// If you want to use it in an expression or statement, use Rust 1.45.0 or later.
///
/// # Examples
/// ```
/// use intertrait::*;
///
/// #[derive(std::fmt::Debug)]
/// enum Data {
/// A, B, C
/// }
/// trait Greet {
/// fn greet(&self);
/// }
/// impl Greet for Data {
/// fn greet(&self) {
/// println!("Hello");
/// }
/// }
///
/// castable_to! { Data => std::fmt::Debug, Greet }
///
/// # fn main() {}
/// ```
///
/// When the type is `Sync + Send` and is used with `Arc`:
/// ```
/// use intertrait::*;
///
/// #[derive(std::fmt::Debug)]
/// enum Data {
/// A, B, C
/// }
/// trait Greet {
/// fn greet(&self);
/// }
/// impl Greet for Data {
/// fn greet(&self) {
/// println!("Hello");
/// }
/// }
/// castable_to! { Data => [sync] std::fmt::Debug, Greet }
///
/// # fn main() {}
/// ```
#[proc_macro]
pub fn castable_to(input: TokenStream) -> TokenStream {
let Casts {
ty,
targets: Targets { flags, paths },
} = parse_macro_input!(input);
paths
.iter()
.map(|t| generate_caster(&ty, t, flags.contains(&Flag::Sync)))
.collect::<proc_macro2::TokenStream>()
.into()
}

View File

@ -1,21 +0,0 @@
//! `cast` module contains traits to provide `cast` method for various references
//! and smart pointers.
//!
//! In source files requiring casts, import all of the traits as follows:
//!
//! ```ignore
//! use intertrait::cast::*;
//! ```
//!
//! Since there exists single trait for each receiver type, the same `cast` method is overloaded.
mod cast_arc;
mod cast_box;
mod cast_mut;
mod cast_rc;
mod cast_ref;
pub use cast_arc::*;
pub use cast_box::*;
pub use cast_mut::*;
pub use cast_rc::*;
pub use cast_ref::*;

View File

@ -1,45 +0,0 @@
use alloc::sync::Arc;
use crate::{caster, CastFromSync};
/// A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting
/// of a trait object for it behind an `Rc` to a trait object for another trait
/// implemented by the underlying value.
///
/// # Examples
/// ```
/// # use std::sync::Arc;
/// # use intertrait::*;
/// use intertrait::cast::*;
///
/// # #[cast_to([sync] Greet)]
/// # struct Data;
/// # trait Source: CastFrom {}
/// # trait Greet {
/// # fn greet(&self);
/// # }
/// # impl Greet for Data {
/// # fn greet(&self) {
/// # println!("Hello");
/// # }
/// # }
/// impl Source for Data {}
/// let data = Data;
/// let source = Arc::new(data);
/// let greet = source.cast::<dyn Greet>();
/// greet.unwrap_or_else(|_| panic!("must not happen")).greet();
/// ```
pub trait CastArc {
/// Casts an `Arc` for this trait into that for type `T`.
fn cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>;
}
/// A blanket implementation of `CastArc` for traits extending `CastFrom`, `Sync`, and `Send`.
impl<S: ?Sized + CastFromSync> CastArc for S {
fn cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>> {
match caster::<T>((*self).type_id()) {
Some(caster) => Ok((caster.cast_arc)(self.arc_any())),
None => Err(self),
}
}
}

View File

@ -1,44 +0,0 @@
use alloc::boxed::Box;
use crate::{caster, CastFrom};
/// A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting
/// of a trait object for it behind a `Box` to a trait object for another trait
/// implemented by the underlying value.
///
/// # Examples
/// ```
/// # use intertrait::*;
/// use intertrait::cast::*;
///
/// # #[cast_to(Greet)]
/// # struct Data;
/// # trait Source: CastFrom {}
/// # trait Greet {
/// # fn greet(&self);
/// # }
/// # impl Greet for Data {
/// # fn greet(&self) {
/// # println!("Hello");
/// # }
/// # }
/// impl Source for Data {}
/// let data = Box::new(Data);
/// let source: Box<dyn Source> = data;
/// let greet = source.cast::<dyn Greet>();
/// greet.unwrap_or_else(|_| panic!("casting failed")).greet();
/// ```
pub trait CastBox {
/// Casts a box to this trait into that of type `T`. If fails, returns the receiver.
fn cast<T: ?Sized + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>>;
}
/// A blanket implementation of `CastBox` for traits extending `CastFrom`.
impl<S: ?Sized + CastFrom> CastBox for S {
fn cast<T: ?Sized + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
match caster::<T>((*self).type_id()) {
Some(caster) => Ok((caster.cast_box)(self.box_any())),
None => Err(self),
}
}
}

View File

@ -1,41 +0,0 @@
use crate::{caster, CastFrom};
/// A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting
/// of a trait object for it behind an mutable reference to a trait object for another trait
/// implemented by the underlying value.
///
/// # Examples
/// ```
/// # use intertrait::*;
/// use intertrait::cast::*;
///
/// # #[cast_to(Greet)]
/// # struct Data;
/// # trait Source: CastFrom {}
/// # trait Greet {
/// # fn greet(&self);
/// # }
/// # impl Greet for Data {
/// # fn greet(&self) {
/// # println!("Hello");
/// # }
/// # }
/// impl Source for Data {}
/// let mut data = Data;
/// let source: &mut dyn Source = &mut data;
/// let greet = source.cast::<dyn Greet>();
/// greet.unwrap().greet();
/// ```
pub trait CastMut {
/// Casts a mutable reference to this trait into that of type `T`.
fn cast<T: ?Sized + 'static>(&mut self) -> Option<&mut T>;
}
/// A blanket implementation of `CastMut` for traits extending `CastFrom`.
impl<S: ?Sized + CastFrom> CastMut for S {
fn cast<T: ?Sized + 'static>(&mut self) -> Option<&mut T> {
let any = self.mut_any();
let caster = caster::<T>((*any).type_id())?;
(caster.cast_mut)(any).into()
}
}

View File

@ -1,44 +0,0 @@
use crate::{caster, CastFrom};
use alloc::rc::Rc;
/// A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting
/// of a trait object for it behind an `Rc` to a trait object for another trait
/// implemented by the underlying value.
///
/// # Examples
/// ```
/// # use std::rc::Rc;
/// # use intertrait::*;
/// use intertrait::cast::*;
///
/// # #[cast_to(Greet)]
/// # struct Data;
/// # trait Source: CastFrom {}
/// # trait Greet {
/// # fn greet(&self);
/// # }
/// # impl Greet for Data {
/// # fn greet(&self) {
/// # println!("Hello");
/// # }
/// # }
/// impl Source for Data {}
/// let data = Data;
/// let source = Rc::new(data);
/// let greet = source.cast::<dyn Greet>();
/// greet.unwrap_or_else(|_| panic!("must not happen")).greet();
/// ```
pub trait CastRc {
/// Casts an `Rc` for this trait into that for type `T`.
fn cast<T: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>>;
}
/// A blanket implementation of `CastRc` for traits extending `CastFrom`.
impl<S: ?Sized + CastFrom> CastRc for S {
fn cast<T: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>> {
match caster::<T>((*self).type_id()) {
Some(caster) => Ok((caster.cast_rc)(self.rc_any())),
None => Err(self),
}
}
}

View File

@ -1,84 +0,0 @@
use core::any::TypeId;
use crate::{caster, CastFrom, Caster};
/// A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting
/// of a trait object for it behind an immutable reference to a trait object for another trait
/// implemented by the underlying value.
///
/// # Examples
/// ## Casting an immutable reference
/// ```
/// # use intertrait::*;
/// use intertrait::cast::*;
///
/// # #[cast_to(Greet)]
/// # struct Data;
/// # trait Source: CastFrom {}
/// # trait Greet {
/// # fn greet(&self);
/// # }
/// # impl Greet for Data {
/// # fn greet(&self) {
/// # println!("Hello");
/// # }
/// # }
/// impl Source for Data {}
/// let data = Data;
/// let source: &dyn Source = &data;
/// let greet = source.cast::<dyn Greet>();
/// greet.unwrap().greet();
/// ```
///
/// ## Testing if a cast is possible
/// ```
/// # use intertrait::*;
/// use intertrait::cast::*;
///
/// # #[cast_to(Greet)]
/// # struct Data;
/// # trait Source: CastFrom {}
/// # trait Greet {
/// # fn greet(&self);
/// # }
/// # impl Greet for Data {
/// # fn greet(&self) {
/// # println!("Hello");
/// # }
/// # }
/// impl Source for Data {}
/// let data = Data;
/// let source: &dyn Source = &data;
/// assert!(source.impls::<dyn Greet>());
/// assert!(!source.impls::<dyn std::fmt::Debug>());
/// ```
pub trait CastRef {
/// Casts a reference to this trait into that of type `T`.
fn cast<T: ?Sized + 'static>(&self) -> Option<&T>;
/// Tests if this trait object can be cast into `T`.
fn impls<T: ?Sized + 'static>(&self) -> bool;
}
/// A blanket implementation of `CastRef` for traits extending `CastFrom`.
impl<S: ?Sized + CastFrom> CastRef for S {
fn cast<T: ?Sized + 'static>(&self) -> Option<&T> {
let any = self.ref_any();
// 获取从 self 到 T 的转换器,如果不存在则返回 None
let caster = caster::<T>(any.type_id())?;
(caster.cast_ref)(any).into()
}
#[cfg(not(target_os = "none"))]
fn impls<T: ?Sized + 'static>(&self) -> bool {
use crate::CASTER_MAP;
CASTER_MAP.contains_key(&(self.type_id(), TypeId::of::<Caster<T>>()))
}
#[cfg(target_os = "none")]
fn impls<T: ?Sized + 'static>(&self) -> bool {
use crate::caster_map;
caster_map().contains_key(&(self.type_id(), TypeId::of::<Caster<T>>()))
}
}

View File

@ -1,28 +0,0 @@
use core::convert::TryInto;
use core::hash::{BuildHasherDefault, Hasher};
use core::mem::size_of;
/// A simple `Hasher` implementation tuned for performance.
#[derive(Default)]
pub struct FastHasher(u64);
/// A `BuildHasher` for `FastHasher`.
pub type BuildFastHasher = BuildHasherDefault<FastHasher>;
impl Hasher for FastHasher {
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, bytes: &[u8]) {
let mut bytes = bytes;
while bytes.len() > size_of::<u64>() {
let (u64_bytes, remaining) = bytes.split_at(size_of::<u64>());
self.0 ^= u64::from_ne_bytes(u64_bytes.try_into().unwrap());
bytes = remaining
}
self.0 ^= bytes
.iter()
.fold(0u64, |result, b| (result << 8) | *b as u64);
}
}

View File

@ -1,587 +0,0 @@
//! A library providing direct casting among trait objects implemented by a type.
//!
//! In Rust, an object of a sub-trait of [`Any`] can be downcast to a concrete type
//! at runtime if the type is known. But no direct casting between two trait objects
//! (i.e. without involving the concrete type of the backing value) is possible
//! (even no coercion from a trait object to that of its super-trait yet).
//!
//! With this crate, any trait object with [`CastFrom`] as its super-trait can be cast directly
//! to another trait object implemented by the underlying type if the target traits are
//! registered beforehand with the macros provided by this crate.
//!
//! # Usage
//! ```
//! use intertrait::*;
//! use intertrait::cast::*;
//!
//! struct Data;
//!
//! trait Source: CastFrom {}
//!
//! trait Greet {
//! fn greet(&self);
//! }
//!
//! #[cast_to]
//! impl Greet for Data {
//! fn greet(&self) {
//! println!("Hello");
//! }
//! }
//!
//! impl Source for Data {}
//!
//! let data = Data;
//! let source: &dyn Source = &data;
//! let greet = source.cast::<dyn Greet>();
//! greet.unwrap().greet();
//! ```
//!
//! Target traits must be explicitly designated beforehand. There are three ways to do it:
//!
//! * [`#[cast_to]`][cast_to] to `impl` item
//! * [`#[cast_to(Trait)]`][cast_to] to type definition
//! * [`castable_to!(Type => Trait1, Trait2)`][castable_to]
//!
//! If the underlying type involved is `Sync + Send` and you want to use it with [`Arc`],
//! use [`CastFromSync`] in place of [`CastFrom`] and add `[sync]` flag before the list
//! of traits in the macros. Refer to the documents for each of macros for details.
//!
//! For casting, refer to traits defined in [`cast`] module.
//!
//! [cast_to]: ./attr.cast_to.html
//! [castable_to]: ./macro.castable_to.html
//! [`CastFrom`]: ./trait.CastFrom.html
//! [`CastFromSync`]: ./trait.CastFromSync.html
//! [`cast`]: ./cast/index.html
//! [`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html
//! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
#![cfg_attr(target_os = "none", no_std)]
extern crate alloc;
extern crate core;
use core::{
any::{Any, TypeId},
marker::{Send, Sync},
};
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::sync::Arc;
use hashbrown::HashMap;
use linkme::distributed_slice;
pub use intertrait_macros::*;
use crate::hasher::BuildFastHasher;
pub mod cast;
mod hasher;
#[doc(hidden)]
pub type BoxedCaster = Box<dyn Any + Send + Sync>;
#[cfg(doctest)]
doc_comment::doctest!("../README.md");
/// A distributed slice gathering constructor functions for [`Caster<T>`]s.
///
/// A constructor function returns `TypeId` of a concrete type involved in the casting
/// and a `Box` of a trait object backed by a [`Caster<T>`].
///
/// [`Caster<T>`]: ./struct.Caster.html
#[doc(hidden)]
#[distributed_slice]
pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..];
/// A `HashMap` mapping `TypeId` of a [`Caster<T>`] to an instance of it.
///
/// [`Caster<T>`]: ./struct.Caster.html
#[cfg(not(target_os = "none"))]
static CASTER_MAP: once_cell::sync::Lazy<HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>> =
once_cell::sync::Lazy::new(|| {
CASTERS
.iter()
.map(|f| {
let (type_id, caster) = f();
((type_id, (*caster).type_id()), caster)
})
.collect()
});
/// CasterMap
///
/// key.0: type_id of source
/// key.1: type_id of target
///
/// value: A BoxedCaster which can cast source to target
#[cfg(target_os = "none")]
static mut CASTER_MAP: Option<HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>> = None;
#[cfg(target_os = "none")]
pub fn caster_map() -> &'static HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher> {
return unsafe {
CASTER_MAP.as_ref().unwrap_or_else(|| {
panic!("intertrait_caster_map() must be called after CASTER_MAP is initialized")
})
};
}
/// Initializes the global [`CASTER_MAP`] with [`CASTERS`].
///
/// no_std环境下需要手动调用此函数初始化CASTER_MAP
#[cfg(target_os = "none")]
pub fn init_caster_map() {
use core::sync::atomic::AtomicBool;
let pd = AtomicBool::new(false);
let r = pd.compare_exchange(
false,
true,
core::sync::atomic::Ordering::SeqCst,
core::sync::atomic::Ordering::SeqCst,
);
if r.is_err() {
panic!("init_caster_map() must be called only once");
}
let hashmap = CASTERS
.iter()
.map(|f| {
let (type_id, caster) = f();
((type_id, (*caster).type_id()), caster)
})
.collect();
unsafe { CASTER_MAP = Some(hashmap) };
}
#[cfg(not(target_os = "none"))]
pub fn init_caster_map() {}
fn cast_arc_panic<T: ?Sized + 'static>(_: Arc<dyn Any + Sync + Send>) -> Arc<T> {
panic!("Prepend [sync] to the list of target traits for Sync + Send types")
}
/// A `Caster` knows how to cast a reference to or `Box` of a trait object for `Any`
/// to a trait object of trait `T`. Each `Caster` instance is specific to a concrete type.
/// That is, it knows how to cast to single specific trait implemented by single specific type.
///
/// An implementation of a trait for a concrete type doesn't need to manually provide
/// a `Caster`. Instead attach `#[cast_to]` to the `impl` block.
#[doc(hidden)]
pub struct Caster<T: ?Sized + 'static> {
/// Casts an immutable reference to a trait object for `Any` to a reference
/// to a trait object for trait `T`.
pub cast_ref: fn(from: &dyn Any) -> &T,
/// Casts a mutable reference to a trait object for `Any` to a mutable reference
/// to a trait object for trait `T`.
pub cast_mut: fn(from: &mut dyn Any) -> &mut T,
/// Casts a `Box` holding a trait object for `Any` to another `Box` holding a trait object
/// for trait `T`.
pub cast_box: fn(from: Box<dyn Any>) -> Box<T>,
/// Casts an `Rc` holding a trait object for `Any` to another `Rc` holding a trait object
/// for trait `T`.
pub cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
/// Casts an `Arc` holding a trait object for `Any + Sync + Send + 'static`
/// to another `Arc` holding a trait object for trait `T`.
pub cast_arc: fn(from: Arc<dyn Any + Sync + Send + 'static>) -> Arc<T>,
}
impl<T: ?Sized + 'static> Caster<T> {
pub fn new(
cast_ref: fn(from: &dyn Any) -> &T,
cast_mut: fn(from: &mut dyn Any) -> &mut T,
cast_box: fn(from: Box<dyn Any>) -> Box<T>,
cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
) -> Caster<T> {
Caster::<T> {
cast_ref,
cast_mut,
cast_box,
cast_rc,
cast_arc: cast_arc_panic,
}
}
pub fn new_sync(
cast_ref: fn(from: &dyn Any) -> &T,
cast_mut: fn(from: &mut dyn Any) -> &mut T,
cast_box: fn(from: Box<dyn Any>) -> Box<T>,
cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
cast_arc: fn(from: Arc<dyn Any + Sync + Send>) -> Arc<T>,
) -> Caster<T> {
Caster::<T> {
cast_ref,
cast_mut,
cast_box,
cast_rc,
cast_arc,
}
}
}
/// Returns a `Caster<S, T>` from a concrete type `S` to a trait `T` implemented by it.
///
/// ## 参数
///
/// - type_id: 源类型的type_id
///
/// T: 目标trait
fn caster<T: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<T>> {
#[cfg(not(target_os = "none"))]
{
CASTER_MAP
.get(&(type_id, TypeId::of::<Caster<T>>()))
.and_then(|caster| caster.downcast_ref::<Caster<T>>())
}
#[cfg(target_os = "none")]
{
caster_map()
.get(&(type_id, TypeId::of::<Caster<T>>()))
.and_then(|caster| caster.downcast_ref::<Caster<T>>())
}
}
/// `CastFrom` must be extended by a trait that wants to allow for casting into another trait.
///
/// It is used for obtaining a trait object for [`Any`] from a trait object for its sub-trait,
/// and blanket implemented for all `Sized + Any + 'static` types.
///
/// # Examples
/// ```ignore
/// trait Source: CastFrom {
/// ...
/// }
/// ```
pub trait CastFrom: Any + 'static {
/// Returns a immutable reference to `Any`, which is backed by the type implementing this trait.
fn ref_any(&self) -> &dyn Any;
/// Returns a mutable reference to `Any`, which is backed by the type implementing this trait.
fn mut_any(&mut self) -> &mut dyn Any;
/// Returns a `Box` of `Any`, which is backed by the type implementing this trait.
fn box_any(self: Box<Self>) -> Box<dyn Any>;
/// Returns an `Rc` of `Any`, which is backed by the type implementing this trait.
fn rc_any(self: Rc<Self>) -> Rc<dyn Any>;
}
/// `CastFromSync` must be extended by a trait that is `Any + Sync + Send + 'static`
/// and wants to allow for casting into another trait behind references and smart pointers
/// especially including `Arc`.
///
/// It is used for obtaining a trait object for [`Any + Sync + Send + 'static`] from an object
/// for its sub-trait, and blanket implemented for all `Sized + Sync + Send + 'static` types.
///
/// # Examples
/// ```ignore
/// trait Source: CastFromSync {
/// ...
/// }
/// ```
pub trait CastFromSync: CastFrom + Sync + Send + 'static {
fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>;
}
impl<T: Sized + Any + 'static> CastFrom for T {
fn ref_any(&self) -> &dyn Any {
self
}
fn mut_any(&mut self) -> &mut dyn Any {
self
}
fn box_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
self
}
}
impl CastFrom for dyn Any + 'static {
fn ref_any(&self) -> &dyn Any {
self
}
fn mut_any(&mut self) -> &mut dyn Any {
self
}
fn box_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
self
}
}
impl<T: Sized + Sync + Send + 'static> CastFromSync for T {
fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> {
self
}
}
impl CastFrom for dyn Any + Sync + Send + 'static {
fn ref_any(&self) -> &dyn Any {
self
}
fn mut_any(&mut self) -> &mut dyn Any {
self
}
fn box_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
self
}
}
impl CastFromSync for dyn Any + Sync + Send + 'static {
fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> {
self
}
}
#[cfg(test)]
mod tests {
extern crate std;
use std::any::{Any, TypeId};
use std::fmt::{Debug, Display};
use linkme::distributed_slice;
use crate::{BoxedCaster, CastFromSync};
use super::cast::*;
use super::*;
#[distributed_slice(super::CASTERS)]
static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster;
#[derive(Debug)]
struct TestStruct;
trait SourceTrait: CastFromSync {}
impl SourceTrait for TestStruct {}
fn create_test_caster() -> (TypeId, BoxedCaster) {
let type_id = TypeId::of::<TestStruct>();
let caster = Box::new(Caster::<dyn Debug> {
cast_ref: |from| from.downcast_ref::<TestStruct>().unwrap(),
cast_mut: |from| from.downcast_mut::<TestStruct>().unwrap(),
cast_box: |from| from.downcast::<TestStruct>().unwrap(),
cast_rc: |from| from.downcast::<TestStruct>().unwrap(),
cast_arc: |from| from.downcast::<TestStruct>().unwrap(),
});
(type_id, caster)
}
#[test]
fn cast_ref() {
let ts = TestStruct;
let st: &dyn SourceTrait = &ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_some());
}
#[test]
fn cast_mut() {
let mut ts = TestStruct;
let st: &mut dyn SourceTrait = &mut ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_some());
}
#[test]
fn cast_box() {
let ts = Box::new(TestStruct);
let st: Box<dyn SourceTrait> = ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_ok());
}
#[test]
fn cast_rc() {
let ts = Rc::new(TestStruct);
let st: Rc<dyn SourceTrait> = ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_ok());
}
#[test]
fn cast_arc() {
let ts = Arc::new(TestStruct);
let st: Arc<dyn SourceTrait> = ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_ok());
}
#[test]
fn cast_ref_wrong() {
let ts = TestStruct;
let st: &dyn SourceTrait = &ts;
let display = st.cast::<dyn Display>();
assert!(display.is_none());
}
#[test]
fn cast_mut_wrong() {
let mut ts = TestStruct;
let st: &mut dyn SourceTrait = &mut ts;
let display = st.cast::<dyn Display>();
assert!(display.is_none());
}
#[test]
fn cast_box_wrong() {
let ts = Box::new(TestStruct);
let st: Box<dyn SourceTrait> = ts;
let display = st.cast::<dyn Display>();
assert!(display.is_err());
}
#[test]
fn cast_rc_wrong() {
let ts = Rc::new(TestStruct);
let st: Rc<dyn SourceTrait> = ts;
let display = st.cast::<dyn Display>();
assert!(display.is_err());
}
#[test]
fn cast_arc_wrong() {
let ts = Arc::new(TestStruct);
let st: Arc<dyn SourceTrait> = ts;
let display = st.cast::<dyn Display>();
assert!(display.is_err());
}
#[test]
fn cast_ref_from_any() {
let ts = TestStruct;
let st: &dyn Any = &ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_some());
}
#[test]
fn cast_mut_from_any() {
let mut ts = TestStruct;
let st: &mut dyn Any = &mut ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_some());
}
#[test]
fn cast_box_from_any() {
let ts = Box::new(TestStruct);
let st: Box<dyn Any> = ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_ok());
}
#[test]
fn cast_rc_from_any() {
let ts = Rc::new(TestStruct);
let st: Rc<dyn Any> = ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_ok());
}
#[test]
fn cast_arc_from_any() {
let ts = Arc::new(TestStruct);
let st: Arc<dyn Any + Send + Sync> = ts;
let debug = st.cast::<dyn Debug>();
assert!(debug.is_ok());
}
#[test]
fn impls_ref() {
let ts = TestStruct;
let st: &dyn SourceTrait = &ts;
assert!(st.impls::<dyn Debug>());
}
#[test]
fn impls_mut() {
let mut ts = TestStruct;
let st: &mut dyn SourceTrait = &mut ts;
assert!((*st).impls::<dyn Debug>());
}
#[test]
fn impls_box() {
let ts = Box::new(TestStruct);
let st: Box<dyn SourceTrait> = ts;
assert!((*st).impls::<dyn Debug>());
}
#[test]
fn impls_rc() {
let ts = Rc::new(TestStruct);
let st: Rc<dyn SourceTrait> = ts;
assert!((*st).impls::<dyn Debug>());
}
#[test]
fn impls_arc() {
let ts = Arc::new(TestStruct);
let st: Arc<dyn SourceTrait> = ts;
assert!((*st).impls::<dyn Debug>());
}
#[test]
fn impls_not_ref() {
let ts = TestStruct;
let st: &dyn SourceTrait = &ts;
assert!(!st.impls::<dyn Display>());
}
#[test]
fn impls_not_mut() {
let mut ts = TestStruct;
let st: &mut dyn Any = &mut ts;
assert!(!(*st).impls::<dyn Display>());
}
#[test]
fn impls_not_box() {
let ts = Box::new(TestStruct);
let st: Box<dyn SourceTrait> = ts;
assert!(!st.impls::<dyn Display>());
}
#[test]
fn impls_not_rc() {
let ts = Rc::new(TestStruct);
let st: Rc<dyn SourceTrait> = ts;
assert!(!(*st).impls::<dyn Display>());
}
#[test]
fn impls_not_arc() {
let ts = Arc::new(TestStruct);
let st: Arc<dyn SourceTrait> = ts;
assert!(!(*st).impls::<dyn Display>());
}
}

View File

@ -1,55 +0,0 @@
use intertrait::cast::*;
use intertrait::*;
struct Data;
trait Source: CastFrom {}
trait Greet {
fn greet(&self);
}
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
trait Greet1 {
fn greet1(&self);
}
impl Greet1 for Data {
fn greet1(&self) {
println!("Hello1");
}
}
trait Greet2 {
fn greet2(&self);
}
impl Greet2 for Data {
fn greet2(&self) {
println!("Hello2");
}
}
impl Source for Data {}
castable_to! { Data => crate::Greet, Greet1, Greet2 }
#[test]
fn test_multi_traits_on_struct() {
let data = Data;
let source: &dyn Source = &data;
let greet = source.cast::<dyn Greet>();
greet.unwrap().greet();
let greet1 = source.cast::<dyn Greet1>();
greet1.unwrap().greet1();
let greet2 = source.cast::<dyn Greet2>();
greet2.unwrap().greet2();
}

View File

@ -1,31 +0,0 @@
use intertrait::cast::*;
use intertrait::*;
#[cast_to(Greet)]
#[allow(dead_code)]
enum Data {
Var1,
Var2(u32),
}
trait Source: CastFrom {}
trait Greet {
fn greet(&self);
}
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
impl Source for Data {}
#[test]
fn test_cast_to_on_enum() {
let data = Data::Var2(1);
let source: &dyn Source = &data;
let greet = source.cast::<dyn Greet>();
greet.unwrap().greet();
}

View File

@ -1,27 +0,0 @@
use intertrait::cast::*;
use intertrait::*;
#[cast_to(Greet)]
struct Data;
trait Source: CastFrom {}
trait Greet {
fn greet(&self);
}
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
impl Source for Data {}
#[test]
fn test_cast_to_on_struct() {
let data = Data;
let source: &dyn Source = &data;
let greet = source.cast::<dyn Greet>();
greet.unwrap().greet();
}

View File

@ -1,33 +0,0 @@
use std::fmt::Debug;
use intertrait::cast::*;
use intertrait::*;
struct I32Data(i32);
trait Source: CastFrom {}
trait Producer {
type Output: Debug;
fn produce(&self) -> Self::Output;
}
#[cast_to]
impl Producer for I32Data {
type Output = i32;
fn produce(&self) -> Self::Output {
self.0
}
}
impl Source for I32Data {}
#[test]
fn test_cast_to_on_trait_impl_with_assoc_type1() {
let data = I32Data(100);
let source: &dyn Source = &data;
let producer = source.cast::<dyn Producer<Output = i32>>();
assert_eq!(producer.unwrap().produce(), data.0);
}

View File

@ -1,35 +0,0 @@
use std::fmt::Debug;
use intertrait::cast::*;
use intertrait::*;
struct Data;
trait Source: CastFrom {}
trait Concat {
type I1: Debug;
type I2: Debug;
fn concat(&self, a: Self::I1, b: Self::I2) -> String;
}
#[cast_to]
impl Concat for Data {
type I1 = i32;
type I2 = &'static str;
fn concat(&self, a: Self::I1, b: Self::I2) -> String {
format!("Data: {} - {}", a, b)
}
}
impl Source for Data {}
#[test]
fn test_cast_to_on_trait_impl_with_assoc_type2() {
let data = Data;
let source: &dyn Source = &data;
let concat = source.cast::<dyn Concat<I1 = i32, I2 = &'static str>>();
assert_eq!(concat.unwrap().concat(101, "hello"), "Data: 101 - hello");
}

View File

@ -1,38 +0,0 @@
use std::fmt::Debug;
use intertrait::cast::*;
use intertrait::*;
struct Data;
trait Source: CastFrom {}
trait Concat<T: Debug> {
type I1: Debug;
type I2: Debug;
fn concat(&self, prefix: T, a: Self::I1, b: Self::I2) -> String;
}
#[cast_to]
impl Concat<String> for Data {
type I1 = i32;
type I2 = &'static str;
fn concat(&self, prefix: String, a: Self::I1, b: Self::I2) -> String {
format!("{}: {} - {}", prefix, a, b)
}
}
impl Source for Data {}
#[test]
fn test_cast_to_on_trait_impl_with_assoc_type3() {
let data = Data;
let source: &dyn Source = &data;
let concat = source.cast::<dyn Concat<String, I1 = i32, I2 = &'static str>>();
assert_eq!(
concat.unwrap().concat("Data".to_owned(), 101, "hello"),
"Data: 101 - hello"
);
}

View File

@ -1,27 +0,0 @@
use intertrait::cast::*;
use intertrait::*;
struct Data;
trait Source: CastFrom {}
trait Greet {
fn greet(&self);
}
#[cast_to]
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
impl Source for Data {}
#[test]
fn test_cast_to_on_trait_impl() {
let data = Data;
let source: &dyn Source = &data;
let greet = source.cast::<dyn Greet>();
greet.unwrap().greet();
}

View File

@ -1,54 +0,0 @@
use intertrait::cast::*;
use intertrait::*;
#[cast_to(Greet, Greet1, Greet2)]
struct Data;
trait Source: CastFrom {}
trait Greet {
fn greet(&self);
}
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
trait Greet1 {
fn greet1(&self);
}
impl Greet1 for Data {
fn greet1(&self) {
println!("Hello1");
}
}
trait Greet2 {
fn greet2(&self);
}
impl Greet2 for Data {
fn greet2(&self) {
println!("Hello2");
}
}
impl Source for Data {}
#[test]
fn test_multi_traits_on_struct() {
let data = Data;
let source: &dyn Source = &data;
let greet = source.cast::<dyn Greet>();
greet.unwrap().greet();
let greet1 = source.cast::<dyn Greet1>();
greet1.unwrap().greet1();
let greet2 = source.cast::<dyn Greet2>();
greet2.unwrap().greet2();
}

View File

@ -1,5 +0,0 @@
#[test]
fn tests() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}

View File

@ -1,27 +0,0 @@
use intertrait::cast::*;
use intertrait::*;
use std::sync::Arc;
#[cast_to([sync, sync] Greet)]
struct Data;
trait Source: CastFromSync {}
trait Greet {
fn greet(&self);
}
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
impl Source for Data {}
fn main() {
let data = Arc::new(Data);
let source: Arc<dyn Source> = data;
let greet = source.cast::<dyn Greet>();
greet.unwrap_or_else(|_| panic!("can't happen")).greet();
}

View File

@ -1,5 +0,0 @@
error: Duplicated flag: sync
--> $DIR/duplicate-flags.rs:5:18
|
5 | #[cast_to([sync, sync] Greet)]
| ^^^^

View File

@ -1,31 +0,0 @@
use intertrait::*;
use intertrait::cast::*;
use std::marker::PhantomData;
#[cast_to(Greet)]
struct Data<T: 'static> {
phantom: PhantomData<T>,
}
trait Source: CastFrom {}
trait Greet {
fn greet(&self);
}
impl<T: 'static> Greet for Data<T> {
fn greet(&self) {
println!("Hello");
}
}
impl<T: 'static> Source for Data<T> {}
fn main() {
let data = Data::<i32> {
phantom: PhantomData,
};
let source: &dyn Source = &data;
let greet = source.cast::<dyn Greet>();
greet.unwrap().greet();
}

View File

@ -1,5 +0,0 @@
error: #[cast_to(..)] can't be used on a generic type definition
--> tests/ui/on-generic-type.rs:6:12
|
6 | struct Data<T: 'static> {
| ^^^^^^^^^^^^

View File

@ -1,14 +0,0 @@
use intertrait::*;
struct Data;
#[cast_to]
impl Data {
fn hello() {
println!("hello!");
}
}
fn main() {
let _ = Data;
}

View File

@ -1,5 +0,0 @@
error: #[cast_to] should only be on an impl of a trait
--> $DIR/on-type-impl.rs:6:6
|
6 | impl Data {
| ^^^^

Some files were not shown because too many files have changed in this diff Show More