use crate::machine::loader::LiveLoadState;
use crate::machine::machine_indices::*;
use crate::machine::streams::*;
-use crate::parser::char_reader::CharReader;
use crate::raw_block::*;
use crate::read::*;
use crate::types::UntypedArenaPtr;
}};
}
-pub fn header_offset_from_payload<Payload: Sized>() -> usize {
- let payload_offset = mem::offset_of!(TypedAllocSlab<Payload>, payload);
- let slab_offset = mem::offset_of!(TypedAllocSlab<Payload>, slab);
+pub fn header_offset_from_payload<T: ?Sized + ArenaAllocated>() -> usize
+where
+ T::Payload: Sized,
+{
+ let payload_offset = mem::offset_of!(TypedAllocSlab<T>, payload);
+ let slab_offset = mem::offset_of!(TypedAllocSlab<T>, slab);
let header_offset = slab_offset + mem::offset_of!(AllocSlab, header);
debug_assert!(payload_offset > header_offset);
}
#[derive(Debug)]
-pub struct TypedArenaPtr<T: ?Sized>(ptr::NonNull<T>);
+pub struct TypedArenaPtr<T: ?Sized + ArenaAllocated>(ptr::NonNull<T::Payload>);
-impl<T: ?Sized + PartialOrd> PartialOrd for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> PartialOrd for TypedArenaPtr<T>
+where
+ T::Payload: PartialOrd,
+{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
(**self).partial_cmp(&**other)
}
}
-impl<T: ?Sized + PartialEq> PartialEq for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> PartialEq for TypedArenaPtr<T>
+where
+ T::Payload: PartialEq,
+{
fn eq(&self, other: &TypedArenaPtr<T>) -> bool {
std::ptr::addr_eq(self.0.as_ptr(), other.0.as_ptr()) || **self == **other
}
}
-impl<T: ?Sized + PartialEq> Eq for TypedArenaPtr<T> {}
+impl<T: ?Sized + ArenaAllocated> Eq for TypedArenaPtr<T> where T::Payload: Eq {}
-impl<T: ?Sized + Ord> Ord for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> Ord for TypedArenaPtr<T>
+where
+ T::Payload: Ord,
+{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
(**self).cmp(&**other)
}
}
-impl<T: ?Sized + Hash> Hash for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> Hash for TypedArenaPtr<T>
+where
+ T::Payload: Hash,
+{
#[inline(always)]
fn hash<H: Hasher>(&self, hasher: &mut H) {
- (self as &T).hash(hasher)
+ (self as &T::Payload).hash(hasher)
}
}
-impl<T: ?Sized> Clone for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> Clone for TypedArenaPtr<T> {
fn clone(&self) -> Self {
*self
}
}
-impl<T: ?Sized> Copy for TypedArenaPtr<T> {}
+impl<T: ?Sized + ArenaAllocated> Copy for TypedArenaPtr<T> {}
-impl<T: ?Sized> Deref for TypedArenaPtr<T> {
- type Target = T;
+impl<T: ?Sized + ArenaAllocated> Deref for TypedArenaPtr<T> {
+ type Target = T::Payload;
fn deref(&self) -> &Self::Target {
unsafe { self.0.as_ref() }
}
}
-impl<T: ?Sized> DerefMut for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> DerefMut for TypedArenaPtr<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.0.as_mut() }
}
}
-impl<T: fmt::Display> fmt::Display for TypedArenaPtr<T> {
+impl<T: ArenaAllocated> fmt::Display for TypedArenaPtr<T>
+where
+ T::Payload: fmt::Display,
+{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", **self)
+ write!(f, "{}", (self as &T::Payload))
}
}
/// - the pointers referee type is correct, safe code depends on the correctness of the type argument
/// - the pointer is allocated in the arena
#[inline]
- pub const unsafe fn new(data: *mut T) -> Self {
+ pub const unsafe fn new(data: *mut T::Payload) -> Self {
unsafe { TypedArenaPtr(ptr::NonNull::new_unchecked(data)) }
}
#[inline]
- pub fn as_ptr(&self) -> *mut T {
+ pub fn as_ptr(&self) -> *mut T::Payload {
self.0.as_ptr()
}
+}
+impl<T: ?Sized + ArenaAllocated> TypedArenaPtr<T>
+where
+ T::Payload: Sized,
+{
#[inline]
pub fn header_ptr(&self) -> *const ArenaHeader {
unsafe { self.as_ptr().byte_sub(T::header_offset_from_payload()) as *const _ }
}
}
-pub trait ArenaAllocated: Sized {
+pub trait ArenaAllocated {
+ type Payload: ?Sized;
+
fn tag() -> ArenaHeaderTag;
- fn header_offset_from_payload() -> usize {
+ fn header_offset_from_payload() -> usize
+ where
+ Self::Payload: Sized,
+ {
header_offset_from_payload::<Self>()
}
/// # Safety
/// - the caller must guarantee that the pointee type of UntypedArenaPtr is Self
- unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr<Self> {
+ unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr<Self>
+ where
+ Self::Payload: Sized,
+ {
// safety:
// - allocated in an arena as from an UntypedArenaPtr
// - caller guarantees the type is correct
- unsafe { TypedArenaPtr::new(ptr.payload_offset().cast_mut().cast::<Self>()) }
+ unsafe { TypedArenaPtr::new(ptr.payload_offset().cast_mut().cast::<Self::Payload>()) }
}
#[allow(clippy::missing_safety_doc)]
- fn alloc(arena: &mut Arena, value: Self) -> TypedArenaPtr<Self> {
+ fn alloc(arena: &mut Arena, value: Self::Payload) -> TypedArenaPtr<Self>
+ where
+ Self::Payload: Sized,
+ {
let size = mem::size_of::<TypedAllocSlab<Self>>();
let slab = Box::new(TypedAllocSlab {
slab: AllocSlab {
}
impl ArenaAllocated for Integer {
+ type Payload = Self;
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::Integer
}
impl ArenaAllocated for Rational {
+ type Payload = Self;
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::Rational
}
impl ArenaAllocated for LiveLoadState {
+ type Payload = Self;
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::LiveLoadState
}
impl ArenaAllocated for TcpListener {
+ type Payload = Self;
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::TcpListener
#[cfg(feature = "http")]
impl ArenaAllocated for HttpListener {
+ type Payload = Self;
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::HttpListener
#[cfg(feature = "http")]
impl ArenaAllocated for HttpResponse {
+ type Payload = Self;
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::HttpResponse
}
impl ArenaAllocated for IndexPtr {
+ type Payload = Self;
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::IndexPtrUndefined
#[repr(C)]
#[derive(Clone, Debug)]
-pub struct TypedAllocSlab<Payload> {
+pub struct TypedAllocSlab<T: ?Sized + ArenaAllocated> {
slab: AllocSlab,
- payload: Payload,
+ payload: T::Payload,
}
-impl<Payload: ArenaAllocated> TypedAllocSlab<Payload> {
+impl<T: ?Sized + ArenaAllocated> TypedAllocSlab<T> {
/// # Safety
/// - ptr points to a valid allocation of Self
#[inline]
- pub unsafe fn to_typed_arena_ptr(ptr: *mut Self) -> TypedArenaPtr<Payload> {
+ pub unsafe fn to_typed_arena_ptr(ptr: *mut Self) -> TypedArenaPtr<T> {
// safety:
// - this is the arena allocation of corresponding type
unsafe { TypedArenaPtr::new(addr_of_mut!((*ptr).payload)) }
drop_typed_slab_in_place!(Rational, value);
}
ArenaHeaderTag::InputFileStream => {
- drop_typed_slab_in_place!(StreamLayout<CharReader<InputFileStream>>, value);
+ drop_typed_slab_in_place!(InputFileStream, value);
}
ArenaHeaderTag::OutputFileStream => {
- drop_typed_slab_in_place!(StreamLayout<OutputFileStream>, value);
+ drop_typed_slab_in_place!(OutputFileStream, value);
}
ArenaHeaderTag::NamedTcpStream => {
- drop_typed_slab_in_place!(StreamLayout<CharReader<NamedTcpStream>>, value);
+ drop_typed_slab_in_place!(NamedTcpStream, value);
}
ArenaHeaderTag::NamedTlsStream => {
#[cfg(feature = "tls")]
- drop_typed_slab_in_place!(StreamLayout<CharReader<NamedTlsStream>>, value);
+ drop_typed_slab_in_place!(NamedTlsStream, value);
}
ArenaHeaderTag::HttpReadStream => {
#[cfg(feature = "http")]
- drop_typed_slab_in_place!(StreamLayout<CharReader<HttpReadStream>>, value);
+ drop_typed_slab_in_place!(HttpReadStream, value);
}
ArenaHeaderTag::HttpWriteStream => {
#[cfg(feature = "http")]
- drop_typed_slab_in_place!(StreamLayout<CharReader<HttpWriteStream>>, value);
+ drop_typed_slab_in_place!(HttpWriteStream, value);
}
ArenaHeaderTag::ReadlineStream => {
- drop_typed_slab_in_place!(StreamLayout<ReadlineStream>, value);
+ drop_typed_slab_in_place!(ReadlineStream, value);
}
ArenaHeaderTag::StaticStringStream => {
- drop_typed_slab_in_place!(StreamLayout<StaticStringStream>, value);
+ drop_typed_slab_in_place!(StaticStringStream, value);
}
ArenaHeaderTag::ByteStream => {
- drop_typed_slab_in_place!(StreamLayout<CharReader<ByteStream>>, value);
+ drop_typed_slab_in_place!(ByteStream, value);
}
ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => {
drop_typed_slab_in_place!(LiveLoadState, value);
drop_typed_slab_in_place!(HttpResponse, value);
}
ArenaHeaderTag::StandardOutputStream => {
- drop_typed_slab_in_place!(StreamLayout<StandardOutputStream>, value);
+ drop_typed_slab_in_place!(StandardOutputStream, value);
}
ArenaHeaderTag::StandardErrorStream => {
- drop_typed_slab_in_place!(StreamLayout<StandardErrorStream>, value);
+ drop_typed_slab_in_place!(StandardErrorStream, value);
}
ArenaHeaderTag::NullStream
| ArenaHeaderTag::IndexPtrUndefined
macro_rules! arena_allocated_impl_for_stream {
($stream_type:ty, $stream_tag:ident) => {
- impl ArenaAllocated for StreamLayout<$stream_type> {
+ impl ArenaAllocated for $stream_tag {
+ type Payload = StreamLayout<$stream_type>;
+
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::$stream_tag
#[derive(Debug, Copy, Clone)]
pub enum Stream {
- Byte(TypedArenaPtr<StreamLayout<CharReader<ByteStream>>>),
- InputFile(TypedArenaPtr<StreamLayout<CharReader<InputFileStream>>>),
- OutputFile(TypedArenaPtr<StreamLayout<OutputFileStream>>),
- StaticString(TypedArenaPtr<StreamLayout<StaticStringStream>>),
- NamedTcp(TypedArenaPtr<StreamLayout<CharReader<NamedTcpStream>>>),
+ Byte(TypedArenaPtr<ByteStream>),
+ InputFile(TypedArenaPtr<InputFileStream>),
+ OutputFile(TypedArenaPtr<OutputFileStream>),
+ StaticString(TypedArenaPtr<StaticStringStream>),
+ NamedTcp(TypedArenaPtr<NamedTcpStream>),
#[cfg(feature = "tls")]
- NamedTls(TypedArenaPtr<StreamLayout<CharReader<NamedTlsStream>>>),
+ NamedTls(TypedArenaPtr<NamedTlsStream>),
#[cfg(feature = "http")]
- HttpRead(TypedArenaPtr<StreamLayout<CharReader<HttpReadStream>>>),
+ HttpRead(TypedArenaPtr<HttpReadStream>),
#[cfg(feature = "http")]
- HttpWrite(TypedArenaPtr<StreamLayout<CharReader<HttpWriteStream>>>),
+ HttpWrite(TypedArenaPtr<HttpWriteStream>),
Null(StreamOptions),
- Readline(TypedArenaPtr<StreamLayout<ReadlineStream>>),
- StandardOutput(TypedArenaPtr<StreamLayout<StandardOutputStream>>),
- StandardError(TypedArenaPtr<StreamLayout<StandardErrorStream>>),
+ Readline(TypedArenaPtr<ReadlineStream>),
+ StandardOutput(TypedArenaPtr<StandardOutputStream>),
+ StandardError(TypedArenaPtr<StandardErrorStream>),
}
-impl From<TypedArenaPtr<StreamLayout<ReadlineStream>>> for Stream {
+impl From<TypedArenaPtr<ReadlineStream>> for Stream {
#[inline]
- fn from(stream: TypedArenaPtr<StreamLayout<ReadlineStream>>) -> Stream {
+ fn from(stream: TypedArenaPtr<ReadlineStream>) -> Stream {
Stream::Readline(stream)
}
}
});
let http_listener = HttpListener { incoming: rx };
- let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena);
+ let http_listener: TypedArenaPtr<HttpListener> =
+ arena_alloc!(http_listener, &mut self.machine_st.arena);
let addr = self.deref_register(2);
self.machine_st.bind(
self.indices.streams.insert(stream);
let stream = stream_as_cell!(stream);
- let handle = arena_alloc!(request.response, &mut self.machine_st.arena);
+ let handle: TypedArenaPtr<HttpResponse> = arena_alloc!(request.response, &mut self.machine_st.arena);
self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
self.machine_st.bind(path.as_var().unwrap(), path_cell);
format!("{}:{}", socket_atom.as_str(), port)
};
- let (tcp_listener, port) = match TcpListener::bind(server_addr).map_err(|e| e.kind()) {
- Ok(tcp_listener) => {
- let port = tcp_listener.local_addr().map(|addr| addr.port()).ok();
+ let (tcp_listener, port): (TypedArenaPtr<TcpListener>, _) =
+ match TcpListener::bind(server_addr).map_err(|e| e.kind()) {
+ Ok(tcp_listener) => {
+ let port = tcp_listener.local_addr().map(|addr| addr.port()).ok();
- if let Some(port) = port {
- (
- arena_alloc!(tcp_listener, &mut self.machine_st.arena),
- port as usize,
- )
- } else {
+ if let Some(port) = port {
+ (
+ arena_alloc!(tcp_listener, &mut self.machine_st.arena),
+ port as usize,
+ )
+ } else {
+ self.machine_st.fail = true;
+ return Ok(());
+ }
+ }
+ Err(ErrorKind::PermissionDenied) => {
+ return Err(self.machine_st.open_permission_error(
+ addr,
+ atom!("socket_server_open"),
+ 2,
+ ));
+ }
+ _ => {
self.machine_st.fail = true;
return Ok(());
}
- }
- Err(ErrorKind::PermissionDenied) => {
- return Err(self.machine_st.open_permission_error(
- addr,
- atom!("socket_server_open"),
- 2,
- ));
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ };
let addr = self.deref_register(3);
self.machine_st.bind(