深入RUST标准库内核—基础类型之整形初步

本文摘自 inside-rust-std-library

RUST的固有(intrinsic)函数库

代码路径:

%USER%.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\intrinsic.rs

intrinsic库函数是指由编译器内置实现的函数,一般如下特点的函数用固有函数:

  1. 与CPU架构相关性很大,必须利用汇编实现或者利用汇编才能具备最高性能的函数,

  2. 和编译器密切相关的函数,由编译器来实现最为合适。

上面内存库章节中已经介绍了内存部分的intrinsic库函数,本节对其他部分做简略介绍

intrinsic 原子操作函数

原子操作函数主要用于多核CPU,多线程CPU时对数据的原子操作。intrinsic库中atomic_xxx及atomic_xxx_xxx类型的函数即为原子操作函数。原子操作函数主要用于并发编程中做临界保护,并且是其他临界保护机制的基础,如Mutex,RWlock等。

数学函数及位操作函数

各种整数及浮点的数学函数实现。这一部分放在intrinsic主要是因为现代CPU对浮点计算由很多支持,这些数学函数由汇编语言来实现更具备效率,那就有必要由编译器来内置实现。

intrinsic 指令优化及调试函数

断言类: assert_xxxx 类型的函数

函数栈:caller_location

小结

intrinsic函数库是从编译器层面完成跨CPU架构的一个手段,intrinsic通常被上层的库所封装。但在操作系统编程和框架编程时,仍然会不可避免的需要接触。

RUST数据类型代码分析

原生数据类型,Option类型,Result类型的某些代码是分析其他模块的基础,因此先对这些类型的部分代码做个基础分析。

整形数据类型

代码目录如下:

%USER%.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\num

无符号整形类型相关库代码分析

标准库用宏简化了无符号整形类型的代码部分。 本节给出若干价值较大的函数,如大小端转换,其他代码则做一个分类简略。代码如下:


macro_rules! uint_impl {

    ($SelfT:ty, $ActualT:ident, $SignedT:ident, $BITS:expr, $MaxV:expr,

        $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,

        $reversed:expr, $le_bytes:expr, $be_bytes:expr,

        $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {

        pub const MIN: Self = 0;

        pub const MAX: Self = !0;

        pub const BITS: u32 = $BITS;

        //利用intrinsics的位函数完成整数的位操作相关函数,这里仅分析一个,其他请参考标准库手册

        pub const fn count_ones(self) -> u32 {

            intrinsics::ctpop(self as $ActualT) as u32

        }

        //其他位操作函数

        ...

        ...

        //内部字节交换,后继大小端变换使用

        pub const fn swap_bytes(self) -> Self {

            intrinsics::bswap(self as $ActualT) as Self

        }

        //big endian 到硬件架构字节序

        pub const fn from_be(x: Self) -> Self {

            #[cfg(target_endian = "big")]

            {

                x

            }

            #[cfg(not(target_endian = "big"))]

            {

                x.swap_bytes()

            }

        }

        //little endian 转换为硬件架构字节序

        pub const fn from_le(x: Self) -> Self {

            #[cfg(target_endian = "little")]

            {

                x

            }

            #[cfg(not(target_endian = "little"))]

            {

                x.swap_bytes()

            }

        }

        //硬件架构字节序到big endian

        pub const fn to_be(self) -> Self { // or not to be?

            #[cfg(target_endian = "big")]

            {

                self

            }

            #[cfg(not(target_endian = "big"))]

            {

                self.swap_bytes()

            }

        }

        //硬件架构字节序到little endian

        pub const fn to_le(self) -> Self {

            #[cfg(target_endian = "little")]

            {

                self

            }

            #[cfg(not(target_endian = "little"))]

            {

                self.swap_bytes()

            }

        }

        //获得大端字节序字节数组

        pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {

            self.to_be().to_ne_bytes()

        }

        //获得小端

        pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {

            self.to_le().to_ne_bytes()

        }

        //硬件平台字节序

        pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {

            unsafe { mem::transmute(self) }

        }

        //从big endian 字节数组获得类型值

        pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {

            Self::from_be(Self::from_ne_bytes(bytes))

        }

        //从little endian 字节数组获得类型值

        pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {

            Self::from_le(Self::from_ne_bytes(bytes))

        }

        //从硬件架构字节序字节数组获得类型值

        pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {

            unsafe { mem::transmute(bytes) }

        }

        //对溢出做检查的加法运算

        //这里每种类型运算都以加法为例,其他诸如减、乘、除、幂次请参考官方标准库手册

        pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {

            let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);

            (a as Self, b)

        }

        //其他的对溢出做检查的数学运算,略

        ...

        ...

        //以边界值取余的加法

        pub const fn wrapping_add(self, rhs: Self) -> Self {

            intrinsics::wrapping_add(self, rhs)

        }

        //以边界值取余的其他数学运算方法,略

        ...

        ...

        //饱和加法,超过边界值结果为边界值

        pub const fn saturating_add(self, rhs: Self) -> Self {

            intrinsics::saturating_add(self, rhs)

        }

        //其他饱和型的数学运算,略

        ...

        ...

        //对加法有效性检查的加法运算,如发生溢出,则返回异常

        pub const fn checked_add(self, rhs: Self) -> Option<Self> {

            let (a, b) = self.overflowing_add(rhs);

            if unlikely!(b) {None} else {Some(a)}

        }

        //无检查add,  是 + 符号的默认调用函数。

        pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {

            // 调用者要保证不发生错误

            unsafe { intrinsics::unchecked_add(self, rhs) }

        }

        //其他对有效性检查的数学运算, 略

        ...

        ...

        pub const fn min_value() -> Self { Self::MIN }

        pub const fn max_value() -> Self { Self::MAX }

}

impl u8 {

    //利用宏实现 u8类型的方法

    uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",

    "[0x12]", "", "" }

    pub const fn is_ascii(&self) -> bool {

        *self & 128 == 0

    }

    //其他ASCII相关函数,请参考标准库手册,略

    ...

    ...

}

//u16 数学函数方法 实现

impl u16 {

    uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",

    "[0x34, 0x12]", "[0x12, 0x34]", "", "" }

    widening_impl! { u16, u32, 16, unsigned }

}

//其他无符号整形的实现,略

...

...

有符号整形数据

与无符号整形数据类似,略。

本作品采用《CC 协议》,转载必须注明作者和本文链接
Warren Ren
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!