1#![allow(dead_code)]
2
3use crate::buffer::{BufferPool, PoolManagement};
4use crate::channel::{self as channel};
5use crate::utils::*;
6use std::io::ErrorKind;
7use std::str;
8use std::sync::Once;
9use std::thread;
10use std::vec;
11
12static ONCE: Once = Once::new();
13
14pub struct ByteBuffer;
15
16impl ByteBuffer {
17 pub fn init(size: usize, capacity: usize) {
18 ONCE.call_once(|| {
19 let mut store = Vec::with_capacity(size);
20 let mut pool = Vec::with_capacity(size);
21
22 (0..size).for_each(|id| {
23 store.push(vec::from_elem(0, capacity));
24 pool.push(id);
25 });
26
27 let (sender, receiver) = channel::bounded(8);
28 thread::spawn(move || {
29 BufferPool::handle_work(receiver);
30 });
31
32 BufferPool::make(store, capacity, sender);
33 });
34 }
35
36 pub fn slice() -> BufferSlice {
37 match BufferPool::exec(BufOp::Reserve(true)) {
38 Some(val) => BufferSlice {
39 id: val,
40 fallback: None,
41 dirty: false,
42 },
43 None => BufferSlice {
44 id: 0,
45 fallback: Some(vec::from_elem(0, BufferPool::default_capacity())),
46 dirty: false,
47 },
48 }
49 }
50
51 pub fn try_slice() -> Option<BufferSlice> {
52 BufferPool::exec(BufOp::Reserve(false))
53 .map(|id|
54 BufferSlice {
55 id,
56 fallback: None,
57 dirty: false,
58 }
59 )
60 }
61
62 #[inline]
63 pub fn extend(additional: usize) {
64 BufferPool::exec(BufOp::Extend(additional));
65 }
66}
67
68pub struct BufferSlice {
69 id: usize,
70 fallback: Option<Vec<u8>>,
71 dirty: bool,
72}
73
74impl BufferSlice {
75 pub(crate) fn new(id: usize, fallback: Option<Vec<u8>>) -> Self {
76 BufferSlice {
77 id,
78 fallback,
79 dirty: false,
80 }
81 }
82
83 pub fn as_writable(&mut self) -> &mut [u8] {
84 self.dirty = true;
85
86 if let Some(ref mut vec) = self.fallback {
87 return vec.as_mut_slice();
88 }
89
90 match BufferPool::get_writable(self.id) {
91 Ok(vec) => vec.as_mut_slice(),
92 Err(_) => {
93 self.fallback = Some(vec::from_elem(0, BufferPool::default_capacity()));
94 if let Some(ref mut vec) = self.fallback {
95 return vec.as_mut_slice();
96 }
97
98 unreachable!();
99 }
100 }
101 }
102
103 pub fn as_writable_vec(&mut self) -> &mut Vec<u8> {
104 self.dirty = true;
105
106 if let Some(ref mut vec) = self.fallback {
107 return vec;
108 }
109
110 match BufferPool::get_writable(self.id) {
111 Ok(vec) => vec,
112 Err(_) => {
113 self.fallback = Some(vec::from_elem(0, BufferPool::default_capacity()));
114 if let Some(vec) = self.fallback.as_mut() {
115 return vec;
116 }
117
118 unreachable!();
119 }
120 }
121 }
122
123 pub fn read(&self) -> Option<&[u8]> {
124 if let Some(ref vec) = self.fallback {
125 return Some(vec.as_slice());
126 }
127
128 match BufferPool::get_readable(self.id) {
129 Ok(vec) => Some(vec.as_slice()),
130 Err(e) => {
131 eprintln!("Failed to read the buffer: {:?}...", e);
132 None
133 }
134 }
135 }
136
137 pub fn read_as_vec(&self) -> Option<&Vec<u8>> {
138 if let Some(ref vec) = self.fallback {
139 return Some(vec);
140 }
141
142 match BufferPool::get_readable(self.id) {
143 Ok(vec) => Some(vec),
144 Err(e) => {
145 eprintln!("Failed to read the buffer: {:?}...", e);
146 None
147 }
148 }
149 }
150
151 pub fn copy_to_vec(&self) -> Vec<u8> {
152 match self.read() {
154 Some(slice) => slice.to_vec(),
155 None => Vec::new(),
156 }
157 }
158
159 pub fn reset(&mut self) {
160 if !self.dirty {
161 return;
162 }
163
164 BufferPool::reset_slice(self.id);
165
166 if let Some(fb) = self.fallback.as_mut() {
167 fb.iter_mut().for_each(|val| *val = 0);
168 }
169 }
170
171 pub fn try_into_string(&self) -> Result<&str, ErrorKind> {
172 if let Some(slice) = self.read() {
173 return match str::from_utf8(slice) {
174 Ok(raw) => Ok(raw),
175 Err(_) => Err(ErrorKind::InvalidData),
176 };
177 }
178
179 Err(ErrorKind::InvalidData)
180 }
181
182 fn len(&self) -> usize {
183 BufferPool::slice_stat(self.id, SliceStatusQuery::Length)
184 }
185
186 fn capacity(&self) -> usize {
187 BufferPool::slice_stat(self.id, SliceStatusQuery::Capacity)
188 }
189}
190
191impl Drop for BufferSlice {
192 fn drop(&mut self) {
193 if self.id == 0 && self.fallback.is_some() {
194 BufferPool::exec(BufOp::ReleaseAndExtend(
195 self.fallback.take().unwrap(),
196 self.dirty,
197 ));
198 } else {
199 BufferPool::reset_and_release(self.id, self.dirty);
200 }
201 }
202}