mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
引入intertrait库,支持trait之间的互相转换 (#395)
* 能过编译(test还没法跑) * 初始化intertrait转换库 * update license of intertrait
This commit is contained in:
parent
bb0e4d4131
commit
fba5623183
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -181,5 +181,5 @@
|
||||
"rust-analyzer.checkOnSave.allTargets": false,
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"./kernel/Cargo.toml"
|
||||
]
|
||||
],
|
||||
}
|
@ -5,9 +5,13 @@ edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[workspace]
|
||||
members = [ "src/libs/intertrait" ]
|
||||
|
||||
# 运行时依赖项
|
||||
[dependencies]
|
||||
x86 = "0.52.0"
|
||||
@ -28,6 +32,8 @@ memoffset = "0.9.0"
|
||||
atomic_enum = "0.2.0"
|
||||
raw-cpuid = "11.0.1"
|
||||
acpi = "5.0.0"
|
||||
intertrait = { path = "src/libs/intertrait" }
|
||||
linkme = "0.2"
|
||||
|
||||
# 构建时依赖项
|
||||
[build-dependencies]
|
||||
|
6
kernel/src/init/c_adapter.rs
Normal file
6
kernel/src/init/c_adapter.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use super::init_intertrait;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_init_intertrait() {
|
||||
init_intertrait();
|
||||
}
|
5
kernel/src/init/mod.rs
Normal file
5
kernel/src/init/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod c_adapter;
|
||||
|
||||
fn init_intertrait() {
|
||||
intertrait::init_caster_map();
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
#![no_std] // <1>
|
||||
#![no_main] // <1>
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(allocator_api)]
|
||||
@ -15,6 +14,11 @@
|
||||
#![feature(trait_upcasting)]
|
||||
#![feature(slice_ptr_get)]
|
||||
#![feature(vec_into_raw_parts)]
|
||||
#![cfg_attr(target_os = "none", no_std)]
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -31,6 +35,7 @@ mod include;
|
||||
mod driver; // 如果driver依赖了libs,应该在libs后面导出
|
||||
mod exception;
|
||||
mod filesystem;
|
||||
mod init;
|
||||
mod ipc;
|
||||
mod mm;
|
||||
mod net;
|
||||
@ -53,6 +58,8 @@ extern crate num;
|
||||
extern crate num_derive;
|
||||
extern crate smoltcp;
|
||||
extern crate thingbuf;
|
||||
#[macro_use]
|
||||
extern crate intertrait;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
extern crate x86;
|
||||
|
||||
@ -65,6 +72,7 @@ use crate::process::ProcessManager;
|
||||
pub static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator;
|
||||
|
||||
/// 全局的panic处理函数
|
||||
#[cfg(target_os = "none")]
|
||||
#[panic_handler]
|
||||
#[no_mangle]
|
||||
pub fn panic(info: &PanicInfo) -> ! {
|
||||
|
18
kernel/src/libs/intertrait/.gitignore
vendored
Normal file
18
kernel/src/libs/intertrait/.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# Cargo lock in subs
|
||||
**/Cargo.lock
|
||||
|
||||
# Generated by Cargo
|
||||
**/target/
|
||||
|
||||
**/*.rs.bk
|
||||
**/*.iml
|
||||
.idea/
|
||||
.vscode/
|
||||
/db/
|
||||
/snapshot/
|
||||
/log/
|
||||
/keys/
|
||||
/test/log/
|
||||
|
||||
# macOS
|
||||
.DS_store
|
27
kernel/src/libs/intertrait/Cargo.toml
Normal file
27
kernel/src/libs/intertrait/Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
||||
[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"
|
||||
|
17
kernel/src/libs/intertrait/LICENSE-MIT
Normal file
17
kernel/src/libs/intertrait/LICENSE-MIT
Normal file
@ -0,0 +1,17 @@
|
||||
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.
|
163
kernel/src/libs/intertrait/README.md
Normal file
163
kernel/src/libs/intertrait/README.md
Normal file
@ -0,0 +1,163 @@
|
||||
# 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)
|
||||
|
23
kernel/src/libs/intertrait/macros/Cargo.toml
Normal file
23
kernel/src/libs/intertrait/macros/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
||||
[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"
|
176
kernel/src/libs/intertrait/macros/LICENSE-APACHE
Normal file
176
kernel/src/libs/intertrait/macros/LICENSE-APACHE
Normal file
@ -0,0 +1,176 @@
|
||||
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
|
17
kernel/src/libs/intertrait/macros/LICENSE-MIT
Normal file
17
kernel/src/libs/intertrait/macros/LICENSE-MIT
Normal file
@ -0,0 +1,17 @@
|
||||
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.
|
76
kernel/src/libs/intertrait/macros/src/args.rs
Normal file
76
kernel/src/libs/intertrait/macros/src/args.rs
Normal file
@ -0,0 +1,76 @@
|
||||
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()?,
|
||||
})
|
||||
}
|
||||
}
|
64
kernel/src/libs/intertrait/macros/src/gen_caster.rs
Normal file
64
kernel/src/libs/intertrait/macros/src/gen_caster.rs
Normal file
@ -0,0 +1,64 @@
|
||||
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]) }
|
||||
}
|
82
kernel/src/libs/intertrait/macros/src/item_impl.rs
Normal file
82
kernel/src/libs/intertrait/macros/src/item_impl.rs
Normal file
@ -0,0 +1,82 @@
|
||||
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
|
||||
}
|
31
kernel/src/libs/intertrait/macros/src/item_type.rs
Normal file
31
kernel/src/libs/intertrait/macros/src/item_type.rs
Normal file
@ -0,0 +1,31 @@
|
||||
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
|
||||
}
|
||||
}
|
145
kernel/src/libs/intertrait/macros/src/lib.rs
Normal file
145
kernel/src/libs/intertrait/macros/src/lib.rs
Normal file
@ -0,0 +1,145 @@
|
||||
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()
|
||||
}
|
21
kernel/src/libs/intertrait/src/cast.rs
Normal file
21
kernel/src/libs/intertrait/src/cast.rs
Normal file
@ -0,0 +1,21 @@
|
||||
//! `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::*;
|
45
kernel/src/libs/intertrait/src/cast/cast_arc.rs
Normal file
45
kernel/src/libs/intertrait/src/cast/cast_arc.rs
Normal file
@ -0,0 +1,45 @@
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
44
kernel/src/libs/intertrait/src/cast/cast_box.rs
Normal file
44
kernel/src/libs/intertrait/src/cast/cast_box.rs
Normal file
@ -0,0 +1,44 @@
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
41
kernel/src/libs/intertrait/src/cast/cast_mut.rs
Normal file
41
kernel/src/libs/intertrait/src/cast/cast_mut.rs
Normal file
@ -0,0 +1,41 @@
|
||||
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()
|
||||
}
|
||||
}
|
44
kernel/src/libs/intertrait/src/cast/cast_rc.rs
Normal file
44
kernel/src/libs/intertrait/src/cast/cast_rc.rs
Normal file
@ -0,0 +1,44 @@
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
84
kernel/src/libs/intertrait/src/cast/cast_ref.rs
Normal file
84
kernel/src/libs/intertrait/src/cast/cast_ref.rs
Normal file
@ -0,0 +1,84 @@
|
||||
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>>()))
|
||||
}
|
||||
}
|
28
kernel/src/libs/intertrait/src/hasher.rs
Normal file
28
kernel/src/libs/intertrait/src/hasher.rs
Normal file
@ -0,0 +1,28 @@
|
||||
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);
|
||||
}
|
||||
}
|
584
kernel/src/libs/intertrait/src/lib.rs
Normal file
584
kernel/src/libs/intertrait/src/lib.rs
Normal file
@ -0,0 +1,584 @@
|
||||
//! 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) };
|
||||
}
|
||||
|
||||
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>());
|
||||
}
|
||||
}
|
55
kernel/src/libs/intertrait/tests/castable_to.rs
Normal file
55
kernel/src/libs/intertrait/tests/castable_to.rs
Normal file
@ -0,0 +1,55 @@
|
||||
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();
|
||||
}
|
31
kernel/src/libs/intertrait/tests/on-enum.rs
Normal file
31
kernel/src/libs/intertrait/tests/on-enum.rs
Normal file
@ -0,0 +1,31 @@
|
||||
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();
|
||||
}
|
27
kernel/src/libs/intertrait/tests/on-struct.rs
Normal file
27
kernel/src/libs/intertrait/tests/on-struct.rs
Normal file
@ -0,0 +1,27 @@
|
||||
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();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
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);
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
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");
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
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"
|
||||
);
|
||||
}
|
27
kernel/src/libs/intertrait/tests/on-trait-impl.rs
Normal file
27
kernel/src/libs/intertrait/tests/on-trait-impl.rs
Normal file
@ -0,0 +1,27 @@
|
||||
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();
|
||||
}
|
54
kernel/src/libs/intertrait/tests/on-type-multi-traits.rs
Normal file
54
kernel/src/libs/intertrait/tests/on-type-multi-traits.rs
Normal file
@ -0,0 +1,54 @@
|
||||
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();
|
||||
}
|
5
kernel/src/libs/intertrait/tests/run.rs
Normal file
5
kernel/src/libs/intertrait/tests/run.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#[test]
|
||||
fn tests() {
|
||||
let t = trybuild::TestCases::new();
|
||||
t.compile_fail("tests/ui/*.rs");
|
||||
}
|
27
kernel/src/libs/intertrait/tests/ui/duplicate-flags.rs
Normal file
27
kernel/src/libs/intertrait/tests/ui/duplicate-flags.rs
Normal file
@ -0,0 +1,27 @@
|
||||
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();
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
error: Duplicated flag: sync
|
||||
--> $DIR/duplicate-flags.rs:5:18
|
||||
|
|
||||
5 | #[cast_to([sync, sync] Greet)]
|
||||
| ^^^^
|
31
kernel/src/libs/intertrait/tests/ui/on-generic-type.rs
Normal file
31
kernel/src/libs/intertrait/tests/ui/on-generic-type.rs
Normal file
@ -0,0 +1,31 @@
|
||||
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();
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
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> {
|
||||
| ^^^^^^^^^^^^
|
14
kernel/src/libs/intertrait/tests/ui/on-type-impl.rs
Normal file
14
kernel/src/libs/intertrait/tests/ui/on-type-impl.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use intertrait::*;
|
||||
|
||||
struct Data;
|
||||
|
||||
#[cast_to]
|
||||
impl Data {
|
||||
fn hello() {
|
||||
println!("hello!");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = Data;
|
||||
}
|
5
kernel/src/libs/intertrait/tests/ui/on-type-impl.stderr
Normal file
5
kernel/src/libs/intertrait/tests/ui/on-type-impl.stderr
Normal file
@ -0,0 +1,5 @@
|
||||
error: #[cast_to] should only be on an impl of a trait
|
||||
--> $DIR/on-type-impl.rs:6:6
|
||||
|
|
||||
6 | impl Data {
|
||||
| ^^^^
|
27
kernel/src/libs/intertrait/tests/ui/unknown-flag.rs
Normal file
27
kernel/src/libs/intertrait/tests/ui/unknown-flag.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use intertrait::cast::*;
|
||||
use intertrait::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cast_to([sync, send] 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();
|
||||
}
|
5
kernel/src/libs/intertrait/tests/ui/unknown-flag.stderr
Normal file
5
kernel/src/libs/intertrait/tests/ui/unknown-flag.stderr
Normal file
@ -0,0 +1,5 @@
|
||||
error: Unknown flag: send
|
||||
--> $DIR/unknown-flag.rs:5:18
|
||||
|
|
||||
5 | #[cast_to([sync, send] Greet)]
|
||||
| ^^^^
|
@ -11,6 +11,7 @@ pub mod lib_ui;
|
||||
pub mod mutex;
|
||||
pub mod notifier;
|
||||
pub mod once;
|
||||
#[macro_use]
|
||||
pub mod printk;
|
||||
pub mod rbtree;
|
||||
#[macro_use]
|
||||
|
@ -1416,10 +1416,12 @@ impl<K: Ord, V> RBTree<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
assert_eq!(m.len(), 0);
|
||||
m.insert(1, 2);
|
||||
@ -1435,6 +1437,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_replace() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
assert_eq!(m.len(), 0);
|
||||
m.insert(2, 4);
|
||||
@ -1446,6 +1449,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_clone() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
assert_eq!(m.len(), 0);
|
||||
m.insert(1, 2);
|
||||
@ -1461,12 +1465,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_empty_remove() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m: RBTree<isize, bool> = RBTree::new();
|
||||
assert_eq!(m.remove(&0), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_iter() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m: RBTree<isize, bool> = RBTree::new();
|
||||
assert_eq!(m.iter().next(), None);
|
||||
assert_eq!(m.iter_mut().next(), None);
|
||||
@ -1477,6 +1483,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_lots_of_insertions() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
|
||||
// Try this a few times to make sure we never screw up the hashmap's
|
||||
@ -1540,6 +1547,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_find_mut() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
m.insert(1, 12);
|
||||
m.insert(2, 8);
|
||||
@ -1554,6 +1562,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_remove() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
m.insert(1, 2);
|
||||
assert_eq!(*m.get(&1).unwrap(), 2);
|
||||
@ -1571,6 +1580,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_is_empty() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
m.insert(1, 2);
|
||||
assert!(!m.is_empty());
|
||||
@ -1580,6 +1590,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_pop() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
m.insert(2, 4);
|
||||
m.insert(1, 2);
|
||||
@ -1595,6 +1606,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_iterate() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
for i in 0..32 {
|
||||
m.insert(i, i * 2);
|
||||
@ -1612,6 +1624,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_keys() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
|
||||
let map: RBTree<_, _> = vec.into_iter().collect();
|
||||
let keys: Vec<_> = map.keys().cloned().collect();
|
||||
@ -1623,6 +1636,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_values() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
|
||||
let map: RBTree<_, _> = vec.into_iter().collect();
|
||||
let values: Vec<_> = map.values().cloned().collect();
|
||||
@ -1634,6 +1648,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_values_mut() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let vec = vec![(1, 1), (2, 2), (3, 3)];
|
||||
let mut map: RBTree<_, _> = vec.into_iter().collect();
|
||||
for value in map.values_mut() {
|
||||
@ -1648,6 +1663,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_find() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m = RBTree::new();
|
||||
assert!(m.get(&1).is_none());
|
||||
m.insert(1, 2);
|
||||
@ -1659,6 +1675,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_eq() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut m1 = RBTree::new();
|
||||
m1.insert(1, 2);
|
||||
m1.insert(2, 3);
|
||||
@ -1677,6 +1694,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_show() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut map = RBTree::new();
|
||||
let empty: RBTree<i32, i32> = RBTree::new();
|
||||
|
||||
@ -1691,6 +1709,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_from_iter() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
|
||||
|
||||
let map: RBTree<_, _> = xs.iter().cloned().collect();
|
||||
@ -1702,6 +1721,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_size_hint() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
|
||||
|
||||
let map: RBTree<_, _> = xs.iter().cloned().collect();
|
||||
@ -1715,6 +1735,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_iter_len() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
|
||||
|
||||
let map: RBTree<_, _> = xs.iter().cloned().collect();
|
||||
@ -1728,6 +1749,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_mut_size_hint() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
|
||||
|
||||
let mut map: RBTree<_, _> = xs.iter().cloned().collect();
|
||||
@ -1741,6 +1763,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_iter_mut_len() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
|
||||
|
||||
let mut map: RBTree<_, _> = xs.iter().cloned().collect();
|
||||
@ -1754,6 +1777,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_index() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut map = RBTree::new();
|
||||
|
||||
map.insert(1, 2);
|
||||
@ -1766,6 +1790,7 @@ mod tests {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_index_nonexistent() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut map = RBTree::new();
|
||||
|
||||
map.insert(1, 2);
|
||||
@ -1777,6 +1802,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_extend_iter() {
|
||||
use crate::libs::rbtree::RBTree;
|
||||
let mut a = RBTree::new();
|
||||
a.insert(1, "one");
|
||||
let mut b = RBTree::new();
|
||||
|
@ -38,6 +38,7 @@ extern void rs_softirq_init();
|
||||
extern void rs_mm_init();
|
||||
extern int rs_video_init();
|
||||
extern void rs_kthread_init();
|
||||
extern void rs_init_intertrait();
|
||||
|
||||
ul bsp_idt_size, bsp_gdt_size;
|
||||
|
||||
@ -101,6 +102,7 @@ void system_initialize()
|
||||
scm_reinit();
|
||||
rs_textui_init();
|
||||
|
||||
rs_init_intertrait();
|
||||
// kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr);
|
||||
io_mfence();
|
||||
|
||||
|
@ -95,6 +95,7 @@ unsafe impl GlobalAlloc for KernelAllocator {
|
||||
}
|
||||
|
||||
/// 内存分配错误处理函数
|
||||
#[cfg(target_os = "none")]
|
||||
#[alloc_error_handler]
|
||||
pub fn global_alloc_err_handler(layout: Layout) -> ! {
|
||||
panic!("global_alloc_error, layout: {:?}", layout);
|
||||
|
Loading…
x
Reference in New Issue
Block a user