深入RUST标准库内核(四 Iterator)— Slice实现

本书github链接:inside-rust-std-library
前面章节参见:
深入RUST标准库内核(序言) - 简书 (jianshu.com)
深入RUST标准库内核(一 概述) - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—Layout/原生指针 - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—NonNull<T>/申请及释放 - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—mem模块/MaybeUninit<T> - 简书 (jianshu.com)
深入RUST标准库内核 (三 基础Trait) 编译器内置Trait - 简书 (jianshu.com)
深入RUST标准库内核(三 基础Trait)— Ops Trait - 简书 (jianshu.com)
深入RUST标准库内核(三 基本Trait)—Range - 简书 (jianshu.com)
深入RUST标准库内核(三 基础Trait)—Index Trait - 简书 (jianshu.com)
深入RUST标准库内核(四 Iterator 实现)— Range实现 - 简书 (jianshu.com)

slice的Iterator实现

首先定义了适合&[T]的Iter结构:

pub struct Iter<'a, T: 'a> {
    //当前元素的指针
    ptr: NonNull<T>,
    //尾元素指针,用ptr == end以快速检测iterator是否为空
    end: *const T, 
    //用来表示iterator与容器类型的生命周期关系
    _marker: PhantomData<&'a T>, 
}

//判断Iterator是否为空的宏
macro_rules! is_empty {
    // 可以满足0字节元素的切片及非0字节元素的切片
    ($self: ident) => {
        //Iter::ptr == Iter::end
        $self.ptr.as_ptr() as *const T == $self.end
    };
}

//取Iterator长度的宏
macro_rules! len {
    ($self: ident) => {{
        let start = $self.ptr;
        let size = size_from_ptr(start.as_ptr());
        //判断元素是否为0字节
        if size == 0 {
            // 用end减start得到0字节元素的切片长度
            ($self.end as usize).wrapping_sub(start.as_ptr() as usize)
        } else {
            //非0字节,用内存字节数除以单元素长度
            let diff = unsafe { unchecked_sub($self.end as usize, start.as_ptr() as usize) };
            unsafe { exact_div(diff, size) }
        }
    }};
}

//用宏实现Iterator Trait
macro_rules! iterator {
    (
        struct $name:ident -> $ptr:ty,
        $elem:ty,
        $raw_mut:tt,
        {$( $mut_:tt )?},
        {$($extra:tt)*}
    ) => {
        // 正向next函数辅助宏,实际的逻辑见post_inc_start函数
        macro_rules! next_unchecked {
            ($self: ident) => {& $( $mut_ )? *$self.post_inc_start(1)}
        }

        // 反向的next函数
        macro_rules! next_back_unchecked {
            ($self: ident) => {& $( $mut_ )? *$self.pre_dec_end(1)}
        }

        // 0元素next的移动
        macro_rules! zst_shrink {
            ($self: ident, $n: ident) => {
                //0元素数组因为不能移动指针,所以移动尾指针
                $self.end = ($self.end as * $raw_mut u8).wrapping_offset(-$n) as * $raw_mut T;
            }
        }
        
        //具体的方法实现
        impl<'a, T> $name<'a, T> {
            // 从Iterator获得切片.
            fn make_slice(&self) -> &'a [T] {
                // ptr::from_raw_parts,由内存首地址和切片长度创建切片指针,然后转换为引用
                unsafe { from_raw_parts(self.ptr.as_ptr(), len!(self)) }
            }

            //实质的next
            unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T {
                if mem::size_of::<T>() == 0 {
                    //0字节元素偏移实现,调整end的值,ptr不变
                    zst_shrink!(self, offset);
                    self.ptr.as_ptr()
                } else {
                    //非0字节元素,返回首地址,首地址然后后移正确的字节
                    let old = self.ptr.as_ptr();
                    self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)) };
                    old
                }
            }

            // 从尾部做Iterator的实际实现函数
            unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T {
                if mem::size_of::<T>() == 0 {
                    //对于0字节元素,从头部及从尾部逻辑相同
                    zst_shrink!(self, offset);
                    self.ptr.as_ptr()
                } else {
                    //尾部的end即偏移后的位置。
                    self.end = unsafe { self.end.offset(-offset) };
                    self.end
                }
            }
        }

        //Iterator的实现
        impl<'a, T> Iterator for $name<'a, T> {
            type Item = $elem;

            #[inline]
            fn next(&mut self) -> Option<$elem> {
                unsafe {
                    //安全性确认
                    assume(!self.ptr.as_ptr().is_null());
                    if mem::size_of::<T>() != 0 {
                        assume(!self.end.is_null());
                    }
                    if is_empty!(self) {
                        //Iter为空的话,返回None
                        None
                    } else {
                        //实际调用post_inc_start(1)
                        Some(next_unchecked!(self))
                    }
                }
            }

            fn size_hint(&self) -> (usize, Option<usize>) {
                let exact = len!(self);
                (exact, Some(exact))
            }

            fn count(self) -> usize {
                len!(self)
            }

            fn nth(&mut self, n: usize) -> Option<$elem> {
                //如果n大于Iter的长度,清空
                if n >= len!(self) {
                    if mem::size_of::<T>() == 0 {
                        self.end = self.ptr.as_ptr();
                    } else {
                        unsafe {
                            self.ptr = NonNull::new_unchecked(self.end as *mut T);
                        }
                    }
                    return None;
                }
                // 否则,失效前n-1个元素,然后做neet
                unsafe {
                    self.post_inc_start(n as isize);
                    Some(next_unchecked!(self))
                }
            }

            fn advance_by(&mut self, n: usize) -> Result<(), usize> {
                //取长度与n中的小值
                let advance = cmp::min(len!(self), n);

                //失效advance-1个值
                unsafe { self.post_inc_start(advance as isize) };
                //返回
                if advance == n { Ok(()) } else { Err(advance) }
            }

            //从尾部Iterator
            fn last(mut self) -> Option<$elem> {
                //实质调用post_dec_end(1)
                self.next_back()
            }

            //其他,略
            ...
            ...
            
        }
    }
}


impl<'a, T> Iter<'a, T> {
    pub(super) fn new(slice: &'a [T]) -> Self {
        let ptr = slice.as_ptr();
        // SAFETY: Similar to `IterMut::new`.
        unsafe {
            assume(!ptr.is_null()); 

            let end = if mem::size_of::<T>() == 0 {
                //如果切片元素是0字节类型,end 为 首地址加 切片长度字节。即每个元素一个字节
                (ptr as *const u8).wrapping_add(slice.len()) as *const T 
            } else {
                //end为slice.len() * mem::<T>::size_of()
                ptr.add(slice.len()) 
            };
            
            //PhantomData会做类型推断,带入T的类型和生命周期
            Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData }
        }
    }
    
    ...
    ...
}
//宏声明
iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, {}}

基本上,一个容器类的Iterator的实现基本上是必须要用ptr及mem模块的函数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容