xref: /DragonOS/kernel/src/libs/casting.rs (revision cde5492f725681ed89abe1e6eb088e05d943d793)
177c928f6Slogin // Copyright (C) DragonOS Community  longjin 2023
277c928f6Slogin 
377c928f6Slogin // This program is free software; you can redistribute it and/or
477c928f6Slogin // modify it under the terms of the GNU General Public License
577c928f6Slogin // as published by the Free Software Foundation; either version 2
677c928f6Slogin // of the License, or (at your option) any later version.
777c928f6Slogin 
877c928f6Slogin // This program is distributed in the hope that it will be useful,
977c928f6Slogin // but WITHOUT ANY WARRANTY; without even the implied warranty of
1077c928f6Slogin // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1177c928f6Slogin // GNU General Public License for more details.
1277c928f6Slogin 
1377c928f6Slogin // You should have received a copy of the GNU General Public License
1477c928f6Slogin // along with this program; if not, write to the Free Software
1577c928f6Slogin // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
1677c928f6Slogin // Or you can visit https://www.gnu.org/licenses/gpl-2.0.html
1777c928f6Slogin #![allow(dead_code)]
1877c928f6Slogin 
1977c928f6Slogin use core::any::Any;
2077c928f6Slogin 
2177c928f6Slogin use alloc::sync::Arc;
2277c928f6Slogin 
2377c928f6Slogin /// @brief 将Arc<dyn xxx>转换为Arc<具体类型>的trait
2477c928f6Slogin ///
2577c928f6Slogin /// 用法:
2677c928f6Slogin ///
2777c928f6Slogin /// ```rust
2877c928f6Slogin /// trait Base: Any + Send + Sync + Debug {
2977c928f6Slogin ///     fn get_name(&self) -> String;
3077c928f6Slogin /// }
3177c928f6Slogin ///
3277c928f6Slogin /// struct A {
3377c928f6Slogin ///    name: String,
3477c928f6Slogin /// }
3577c928f6Slogin ///
3677c928f6Slogin /// impl DowncastArc for dyn Base {
3777c928f6Slogin ///     fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> {
3877c928f6Slogin ///         return self;
3977c928f6Slogin ///     }
4077c928f6Slogin /// }
4177c928f6Slogin ///
4277c928f6Slogin /// impl Base for A {
4377c928f6Slogin ///    fn get_name(&self) -> String {
4477c928f6Slogin ///       return self.name.clone();
4577c928f6Slogin ///   }
4677c928f6Slogin /// }
4777c928f6Slogin ///
4877c928f6Slogin /// fn test() {
4977c928f6Slogin ///     let a = A { name: "a".to_string() };
5077c928f6Slogin 
5177c928f6Slogin ///     let a_arc: Arc<dyn Base> = Arc::new(a) as Arc<dyn Base>;
5277c928f6Slogin ///     let a_arc2: Option<Arc<A>> = a_arc.downcast_arc::<A>();
5377c928f6Slogin ///     assert!(a_arc2.is_some());
5477c928f6Slogin /// }
5577c928f6Slogin /// ```
56*cde5492fSlogin pub trait DowncastArc: Any + Send + Sync {
5777c928f6Slogin     /// 请在具体类型中实现这个函数,返回self
as_any_arc(self: Arc<Self>) -> Arc<dyn Any>5877c928f6Slogin     fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any>;
5977c928f6Slogin 
6077c928f6Slogin     /// @brief 将Arc<dyn xxx>转换为Arc<具体类型>
6177c928f6Slogin     ///
6277c928f6Slogin     /// 如果Arc<dyn xxx>是Arc<具体类型>,则返回Some(Arc<具体类型>),否则返回None
6377c928f6Slogin     ///
6477c928f6Slogin     /// @param self Arc<dyn xxx>
downcast_arc<T: Any + Send + Sync>(self: Arc<Self>) -> Option<Arc<T>>6577c928f6Slogin     fn downcast_arc<T: Any + Send + Sync>(self: Arc<Self>) -> Option<Arc<T>> {
6677c928f6Slogin         let x: Arc<dyn Any> = self.as_any_arc();
6777c928f6Slogin         if x.is::<T>() {
6877c928f6Slogin             // into_raw不会改变引用计数
6977c928f6Slogin             let p = Arc::into_raw(x);
7077c928f6Slogin             let new = unsafe { Arc::from_raw(p as *const T) };
7177c928f6Slogin             return Some(new);
7277c928f6Slogin         }
7377c928f6Slogin         return None;
7477c928f6Slogin     }
7577c928f6Slogin }
76