remove some unsafe blocks

This commit is contained in:
Nikolay Kim 2021-02-19 03:23:42 +06:00
parent f2c51a0fa1
commit 4225e093cc
5 changed files with 46 additions and 87 deletions

View file

@ -70,7 +70,7 @@ serde_json = "1.0"
serde_urlencoded = "0.7.0" serde_urlencoded = "0.7.0"
socket2 = "0.3.12" socket2 = "0.3.12"
url = "2.1" url = "2.1"
time = { version = "0.2.11", default-features = false, features = ["std"] } time = { version = "0.2.15", default-features = false, features = ["std"] }
coo-kie = { version = "0.14.2", package = "cookie", optional = true } coo-kie = { version = "0.14.2", package = "cookie", optional = true }
tokio = "0.2.6" tokio = "0.2.6"

View file

@ -231,7 +231,7 @@ where
// remove written data // remove written data
if written == len { if written == len {
// flushed same amount as in buffer, we dont need to reallocate // SAFETY: flushed same amount as in buffer, we dont need to reallocate
unsafe { buf.set_len(0) } unsafe { buf.set_len(0) }
} else { } else {
buf.advance(written); buf.advance(written);

View file

@ -1,6 +1,4 @@
use std::{ use std::{cell::Cell, ptr::copy_nonoverlapping, rc::Rc, time::Duration};
cell::UnsafeCell, fmt, fmt::Write, ptr::copy_nonoverlapping, rc::Rc, time::Duration,
};
use bytes::BytesMut; use bytes::BytesMut;
use futures::{future, FutureExt}; use futures::{future, FutureExt};
@ -9,9 +7,6 @@ use time::OffsetDateTime;
use crate::framed::Timer; use crate::framed::Timer;
use crate::rt::time::{delay_for, delay_until, Delay, Instant}; use crate::rt::time::{delay_for, delay_until, Delay, Instant};
// "Sun, 06 Nov 1994 08:49:37 GMT".len()
const DATE_VALUE_LENGTH: usize = 29;
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
/// Server keep-alive setting /// Server keep-alive setting
pub enum KeepAlive { pub enum KeepAlive {
@ -155,40 +150,13 @@ impl<S, X, U> DispatcherConfig<S, X, U> {
} }
} }
#[derive(Copy, Clone)] // "Sun, 06 Nov 1994 08:49:37 GMT".len()
pub(super) struct Date { const DATE_VALUE_LENGTH_HDR: usize = 39;
pub(super) bytes: [u8; DATE_VALUE_LENGTH], const DATE_VALUE_DEFAULT: [u8; DATE_VALUE_LENGTH_HDR] = [
pos: usize, b'd', b'a', b't', b'e', b':', b' ', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0',
} b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0',
b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'\r', b'\n', b'\r', b'\n',
impl Date { ];
fn new() -> Date {
let mut date = Date {
bytes: [0; DATE_VALUE_LENGTH],
pos: 0,
};
date.update();
date
}
fn update(&mut self) {
self.pos = 0;
write!(
self,
"{}",
OffsetDateTime::now_utc().format("%a, %d %b %Y %H:%M:%S GMT")
)
.unwrap();
}
}
impl fmt::Write for Date {
fn write_str(&mut self, s: &str) -> fmt::Result {
let len = s.len();
self.bytes[self.pos..self.pos + len].copy_from_slice(s.as_bytes());
self.pos += len;
Ok(())
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct DateService(Rc<DateServiceInner>); pub struct DateService(Rc<DateServiceInner>);
@ -200,24 +168,32 @@ impl Default for DateService {
} }
struct DateServiceInner { struct DateServiceInner {
current: UnsafeCell<Option<(Date, Instant)>>, current: Cell<bool>,
current_time: Cell<Instant>,
current_date: Cell<[u8; DATE_VALUE_LENGTH_HDR]>,
} }
impl DateServiceInner { impl DateServiceInner {
fn new() -> Self { fn new() -> Self {
DateServiceInner { DateServiceInner {
current: UnsafeCell::new(None), current: Cell::new(false),
current_time: Cell::new(Instant::now()),
current_date: Cell::new(DATE_VALUE_DEFAULT),
} }
} }
fn reset(&self) { fn reset(&self) {
unsafe { (&mut *self.current.get()).take() }; self.current.set(false);
} }
fn update(&self) { fn update(&self) {
let now = Instant::now(); self.current.set(true);
let date = Date::new(); self.current_time.set(Instant::now());
*(unsafe { &mut *self.current.get() }) = Some((date, now));
let mut bytes = DATE_VALUE_DEFAULT;
let dt = OffsetDateTime::now_utc().format("%a, %d %b %Y %H:%M:%S GMT");
bytes[6..35].copy_from_slice(dt.as_ref());
self.current_date.set(bytes);
} }
} }
@ -227,7 +203,7 @@ impl DateService {
} }
fn check_date(&self) { fn check_date(&self) {
if unsafe { (&*self.0.current.get()).is_none() } { if !self.0.current.get() {
self.0.update(); self.0.update();
// periodic date update // periodic date update
@ -241,32 +217,27 @@ impl DateService {
fn now(&self) -> Instant { fn now(&self) -> Instant {
self.check_date(); self.check_date();
unsafe { (&*self.0.current.get()).as_ref().unwrap().1 } self.0.current_time.get()
} }
pub(super) fn set_date<F: FnMut(&Date)>(&self, mut f: F) { pub(super) fn set_date<F: FnMut(&[u8])>(&self, mut f: F) {
self.check_date(); self.check_date();
f(&unsafe { (&*self.0.current.get()).as_ref().unwrap().0 }) let date = self.0.current_date.get();
f(&date[6..35])
} }
#[doc(hidden)] #[doc(hidden)]
pub fn set_date_header(&self, dst: &mut BytesMut) { pub fn set_date_header(&self, dst: &mut BytesMut) {
const HEAD: &[u8] = b"date: "; // SAFETY: reserves exact size
const TAIL: &[u8] = b"\r\n\r\n"; let len = dst.len();
// date bytes len dst.reserve(DATE_VALUE_LENGTH_HDR);
const N: usize = 29;
const TOTAL: usize = 39;
dst.reserve(TOTAL);
// SAFETY: previous reserve exact size
unsafe { unsafe {
let buf = dst.as_mut_ptr().add(dst.len()); copy_nonoverlapping(
copy_nonoverlapping(HEAD.as_ptr(), buf, HEAD.len()); self.0.current_date.as_ptr().cast(),
self.set_date(|date| { dst.as_mut_ptr().add(len),
copy_nonoverlapping(date.bytes.as_ptr(), buf.add(HEAD.len()), N) DATE_VALUE_LENGTH_HDR,
}); );
copy_nonoverlapping(TAIL.as_ptr(), buf.add(N + HEAD.len()), TAIL.len()); dst.set_len(len + DATE_VALUE_LENGTH_HDR)
dst.set_len(dst.len() + TOTAL)
} }
} }
} }
@ -275,17 +246,12 @@ impl DateService {
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn test_date_len() {
assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
}
#[ntex_rt::test] #[ntex_rt::test]
async fn test_date() { async fn test_date() {
let date = DateService::default(); let date = DateService::default();
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10); let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH_HDR);
date.set_date_header(&mut buf1); date.set_date_header(&mut buf1);
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10); let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH_HDR);
date.set_date_header(&mut buf2); date.set_date_header(&mut buf2);
assert_eq!(buf1, buf2); assert_eq!(buf1, buf2);
} }

View file

@ -205,8 +205,7 @@ where
// set date header // set date header
if !has_date { if !has_date {
let mut bytes = BytesMut::with_capacity(29); let mut bytes = BytesMut::with_capacity(29);
self.timer self.timer.set_date(|date| bytes.extend_from_slice(date));
.set_date(|date| bytes.extend_from_slice(&date.bytes));
res.headers_mut().insert(DATE, unsafe { res.headers_mut().insert(DATE, unsafe {
HeaderValue::from_maybe_shared_unchecked(bytes.freeze()) HeaderValue::from_maybe_shared_unchecked(bytes.freeze())
}); });

View file

@ -1,5 +1,5 @@
//! A synchronization primitive for task wakeup. //! A synchronization primitive for task wakeup.
use std::{cell::UnsafeCell, fmt, marker::PhantomData, rc, task::Waker}; use std::{cell::Cell, fmt, marker::PhantomData, rc, task::Waker};
/// A synchronization primitive for task wakeup. /// A synchronization primitive for task wakeup.
/// ///
@ -19,7 +19,7 @@ use std::{cell::UnsafeCell, fmt, marker::PhantomData, rc, task::Waker};
/// `wake`. /// `wake`.
#[derive(Default)] #[derive(Default)]
pub struct LocalWaker { pub struct LocalWaker {
pub(crate) waker: UnsafeCell<Option<Waker>>, waker: Cell<Option<Waker>>,
_t: PhantomData<rc::Rc<()>>, _t: PhantomData<rc::Rc<()>>,
} }
@ -27,23 +27,17 @@ impl LocalWaker {
/// Create an `LocalWaker`. /// Create an `LocalWaker`.
pub fn new() -> Self { pub fn new() -> Self {
LocalWaker { LocalWaker {
waker: UnsafeCell::new(None), waker: Cell::new(None),
_t: PhantomData, _t: PhantomData,
} }
} }
#[inline]
/// Check if waker has been registered.
pub fn is_registered(&self) -> bool {
unsafe { (*self.waker.get()).is_some() }
}
#[inline] #[inline]
/// Registers the waker to be notified on calls to `wake`. /// Registers the waker to be notified on calls to `wake`.
/// ///
/// Returns `true` if waker was registered before. /// Returns `true` if waker was registered before.
pub fn register(&self, waker: &Waker) -> bool { pub fn register(&self, waker: &Waker) -> bool {
unsafe { self.waker.get().replace(Some(waker.clone())).is_some() } self.waker.replace(Some(waker.clone())).is_some()
} }
#[inline] #[inline]
@ -60,7 +54,7 @@ impl LocalWaker {
/// ///
/// If a waker has not been registered, this returns `None`. /// If a waker has not been registered, this returns `None`.
pub fn take(&self) -> Option<Waker> { pub fn take(&self) -> Option<Waker> {
unsafe { (*self.waker.get()).take() } self.waker.take()
} }
} }