rust_rsm/common/
ringbuf.rs

1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4
5///环形队列实现,添加数据从队尾开始,取数据从队头开始
6/// 可以检查ringbuf中是否存在一个完整的应用层报文
7use std::{cmp,alloc,mem,ptr};
8use super::errcode;
9
10///回调函数,确定目前的ringbuf中是否至少已经有一个完整的报文了,方便进行组包处理;
11/// 回调函数第一个参数为当前ringbuf中的前8个字节,如果报文完整,则返回完整的报文长度,否则返回失败
12pub type fn_check_msg_interity=fn(start_bytes:&[u8],req_size:usize,total:usize)->Result<usize,errcode::RESULT>;
13
14pub struct ring_buffer_t {
15    buffer:*mut u8,
16    size:usize,
17    head:usize,
18    tail:usize,
19    fn_call_back:Option<fn_check_msg_interity>,
20}
21
22
23//Head==usize::MAX,the buffer length=0, head=tail, the buffer length=self.capacity
24impl ring_buffer_t {
25    pub fn new(capacity:usize,call_back:Option<fn_check_msg_interity>)->Option<Self> {
26        let p=unsafe { alloc::alloc(alloc::Layout::from_size_align_unchecked(capacity, 1)) };
27        if p.is_null() {
28            return None
29        }
30        return Some(Self {
31            buffer:p,
32            size:capacity,
33            head:usize::MAX,
34            tail:0,
35            fn_call_back:call_back,
36        })
37    }
38
39    pub fn len(&self)->usize {
40        if self.head==usize::MAX {
41            return 0
42        }
43        if self.head==self.tail {
44            return self.size
45        }
46        (self.tail+self.size-self.head) % self.size
47    }
48
49    pub fn buffer_available(&self)->usize {
50        self.size-self.len()
51    }
52
53    //往ringbuf添加一块数据,添加到尾部
54    pub fn put_data(&mut self,buf:&[u8])->errcode::RESULT {
55        if buf.len()>self.buffer_available() {
56            return errcode::ERROR_OUTOF_MEM
57        }
58        if buf.len()==0 {
59            return errcode::ERROR_NO_DATA
60        }
61        let first_slice_len=cmp::min(buf.len(),self.size-self.tail);
62        unsafe {
63        if first_slice_len>=buf.len() {
64            ptr::copy_nonoverlapping(buf.as_ptr(), self.buffer.offset(self.tail as isize), buf.len());
65        } else {
66            ptr::copy_nonoverlapping(buf.as_ptr(), self.buffer.offset(self.tail as isize), first_slice_len);
67            ptr::copy_nonoverlapping(buf[first_slice_len..].as_ptr(), self.buffer, buf.len()-first_slice_len);
68        }
69        }
70        if self.head==usize::MAX {
71            self.head=self.tail;
72        }
73        self.tail=(self.tail+buf.len()) % self.size;
74
75        errcode::RESULT_SUCCESS
76    }
77
78    ///从指定的偏移量处复制长度为copy_len的数据, the caller must checked the buffer and length is valid
79    fn copy_data_uncheck(&self,offset:usize,copy_len:usize,buf:&mut [u8]) {
80        let index=(self.head+offset) % self.size;
81        let first_slice_len = if index>self.tail {
82            cmp::min(copy_len,self.size-index)
83        } else {
84            copy_len
85        };
86        unsafe {
87        if first_slice_len==copy_len {
88            ptr::copy_nonoverlapping(self.buffer.offset(index as isize), buf.as_mut_ptr(),copy_len);
89        } else {
90            ptr::copy_nonoverlapping(self.buffer.offset(index as isize), buf.as_mut_ptr(), first_slice_len);
91            ptr::copy_nonoverlapping(self.buffer, buf[first_slice_len..].as_mut_ptr(),copy_len-first_slice_len);
92        }
93        }       
94    }
95    //从ringbuf首部开始取一块数据,并从buffer中移除,会回调检查buffer中是否有至少一个报文
96    pub fn pull_data(&mut self,max_len:usize,buf:&mut [u8])->Result<usize,errcode::RESULT> {
97        if self.len()==0 {
98            return Err(errcode::ERROR_NO_DATA)
99        }
100        if buf.len()==0 {
101            return Err(errcode::ERROR_BUFFER_TOO_SMALL)
102        }
103        let req_len = cmp::min(max_len, buf.len());
104        let data_len = match self.fn_call_back {
105            None=> {
106                cmp::min(req_len, self.len())
107            },
108            Some(fn_cb)=>{
109                let mut hdr=[0u8;8];
110                let l=match self.peek_data(0, hdr.len(), &mut hdr) {
111                    Ok(l)=>l,
112                    Err(e)=>return Err(e),
113                };
114
115                if let Ok(len)= fn_cb(&hdr[0..l],req_len,self.len()) {
116                    len
117                } else {
118                    return Err(errcode::ERROR_NO_OP)
119                }
120            },
121        };
122        
123        self.copy_data_uncheck(0,data_len,buf);
124        if self.len()<=data_len {
125            self.tail=0;
126            self.head=usize::MAX;
127        } else {
128            self.head=(self.head+data_len) % self.size;
129        }        
130 
131        Ok(data_len)
132    }
133    //从ringbuf指定偏移量取指定长度的报文,并不从缓冲区中移除数据
134    pub fn peek_data(&self,offset:usize,max_len:usize,buf:&mut [u8])->Result<usize,errcode::RESULT> {
135        if offset>=self.len() {
136            return Err(errcode::ERROR_NO_DATA)
137        }
138
139        let copy_len=cmp::min(self.len()-offset,cmp::min(max_len,buf.len()));
140        self.copy_data_uncheck(offset,copy_len, buf);
141
142        Ok(copy_len)
143    }
144
145}
146
147impl Drop for ring_buffer_t {
148    fn drop(&mut self) {
149        if self.buffer.is_null() {
150            return
151        }
152        unsafe {
153            alloc::dealloc(self.buffer, alloc::Layout::from_size_align_unchecked(self.size, 1));
154            self.buffer=ptr::null_mut();
155        }
156    }
157}
158
159use super::spin_lock_t;
160pub struct ts_ring_buffer_t {
161    lock:spin_lock_t,
162    ring:ring_buffer_t,
163}
164
165//thread safe wrapper for ring_buffer implementation
166impl ts_ring_buffer_t {
167    pub fn new(capacity:usize,call_back:Option<fn_check_msg_interity>)->Option<Self> {
168        let ring=ring_buffer_t::new(capacity, call_back);
169        match ring {
170            None=>return None,
171            Some(r)=>{
172                return Some(Self { lock: spin_lock_t::new(), ring: r })
173            }
174        }
175        
176    }
177
178    pub fn len(&self)->usize {
179        self.lock.lock();
180        let l=self.ring.len();
181        self.lock.unlock();
182        l
183    }
184
185    pub fn buffer_available(&self)->usize {
186        self.lock.lock();
187        let r=self.ring.buffer_available();
188        self.lock.unlock();
189        r
190    }
191
192    pub fn put_data(&mut self,buf:&[u8])->errcode::RESULT {
193        self.lock.lock();
194        let r=self.ring.put_data(buf);
195        self.lock.unlock();
196        r
197    }
198    pub fn pull_data(&mut self,max_len:usize,buf:&mut [u8])->Result<usize,errcode::RESULT> {
199        self.lock.lock();
200        let r=self.ring.pull_data(max_len, buf);
201        self.lock.unlock();
202        r        
203    }
204
205    pub fn peek_data(&self,offset:usize,max_len:usize,buf:&mut [u8])->Result<usize,errcode::RESULT> {
206        self.lock.lock();
207        let r=self.ring.peek_data(offset, max_len, buf);
208        self.lock.unlock();
209        r    
210    }
211
212}