inlining
This commit is contained in:
parent
e40ea67e21
commit
4f7df3ddb5
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
pub mod plain;
|
pub mod plain;
|
||||||
|
|
||||||
use std::{error::Error, marker::PhantomData, rc::Rc};
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
use crate::std::*;
|
use crate::std::*;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
//! [`Plain`] type for storing raw byte sequnces.
|
//! [`Plain`] type for storing raw byte sequnces.
|
||||||
|
|
||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use crate::std::atomic::*;
|
use crate::std::atomic::*;
|
||||||
|
|
||||||
/// Raw bytes storage. Use [`Plain::raw`] to get the data.
|
/// Raw bytes storage. Use [`Plain::raw`] to get the data.
|
||||||
|
@ -1 +1,3 @@
|
|||||||
|
//! Standard generic collections.
|
||||||
|
|
||||||
pub mod stack;
|
pub mod stack;
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
|
//! Basic implementation of a stack/linked list.
|
||||||
|
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
|
use crate::std::inlining::*;
|
||||||
use crate::std::nullable::*;
|
use crate::std::nullable::*;
|
||||||
use crate::std::*;
|
use crate::std::*;
|
||||||
|
|
||||||
|
/// Node containing a (nullable) reference to the next node and an element.
|
||||||
pub struct StackNode<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
pub struct StackNode<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
||||||
|
/// Reference comes first due to being inlineable.
|
||||||
pub rest: Stack<'a, Ctx, A>,
|
pub rest: Stack<'a, Ctx, A>,
|
||||||
|
/// Unlike the original implementation in Python, doesn't default to using Point.
|
||||||
pub element: Rc<A>,
|
pub element: Rc<A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Stack<'a, Ctx, A> = Nullable<'a, Ctx, StackNode<'a, Ctx, A>>;
|
/// Type representing a stack, an alias to a [Nullable] of a [StackNode].
|
||||||
|
pub type Stack<'a, Ctx, A> = Nullable<'a, Ctx, StackNode<'a, Ctx, A>>;
|
||||||
|
|
||||||
pub struct StackNodeFactory<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
pub struct StackNodeFactory<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
||||||
element_factory: A::Fctr,
|
element_factory: A::Fctr,
|
||||||
@ -106,16 +113,26 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Factory<'a, Ctx>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See [`StackVecResult`].
|
||||||
pub type StackFaiure<'a, Ctx, A> = ResolutionFailure<'a, Ctx, StackNode<'a, Ctx, A>>;
|
pub type StackFaiure<'a, Ctx, A> = ResolutionFailure<'a, Ctx, StackNode<'a, Ctx, A>>;
|
||||||
|
|
||||||
|
/// See [`StackVecWrapped`].
|
||||||
pub type StackVecResult<'a, Ctx, A> = Result<Vec<Rc<A>>, StackFaiure<'a, Ctx, A>>;
|
pub type StackVecResult<'a, Ctx, A> = Result<Vec<Rc<A>>, StackFaiure<'a, Ctx, A>>;
|
||||||
|
|
||||||
|
/// See [`ExtStack::vec`].
|
||||||
pub type StackVecWrapped<'a, Ctx, A> = Wrapped<'a, Ctx, StackVecResult<'a, Ctx, A>>;
|
pub type StackVecWrapped<'a, Ctx, A> = Wrapped<'a, Ctx, StackVecResult<'a, Ctx, A>>;
|
||||||
|
|
||||||
|
/// Extention trait with helper methods for [Stack]s.
|
||||||
pub trait ExtStack<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>: Mentionable<'a, Ctx> {
|
pub trait ExtStack<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>: Mentionable<'a, Ctx> {
|
||||||
|
/// Get an empty stack ([`Nullable::Null`]).
|
||||||
fn empty(factory: A::Fctr) -> Self;
|
fn empty(factory: A::Fctr) -> Self;
|
||||||
|
/// Get the corresponding factory.
|
||||||
fn f(factory: A::Fctr) -> Self::Fctr;
|
fn f(factory: A::Fctr) -> Self::Fctr;
|
||||||
|
/// Add one element.
|
||||||
|
///
|
||||||
|
/// Note: consumes the stack. For non-consuming version do `.clone()` before adding.
|
||||||
fn add(self, element: A) -> Self;
|
fn add(self, element: A) -> Self;
|
||||||
|
/// Collect all the elements into a [`Vec`].
|
||||||
fn vec(self) -> StackVecWrapped<'a, Ctx, A>;
|
fn vec(self) -> StackVecWrapped<'a, Ctx, A>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,3 +221,28 @@ mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> InlineableFactory
|
||||||
|
for StackNodeFactory<'a, Ctx, A>
|
||||||
|
where
|
||||||
|
A::Fctr: InlineableFactory,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> FixedSizeFactory
|
||||||
|
for StackNodeFactory<'a, Ctx, A>
|
||||||
|
where
|
||||||
|
A::Fctr: FixedSizeFactory,
|
||||||
|
{
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
Stack::<'a, Ctx, A>::SIZE + self.element_factory.size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> ConstSizeFactory
|
||||||
|
for StackNodeFactory<'a, Ctx, A>
|
||||||
|
where
|
||||||
|
A::Fctr: ConstSizeFactory,
|
||||||
|
{
|
||||||
|
const SIZE: usize = { Stack::<'a, Ctx, A>::SIZE + A::Fctr::SIZE };
|
||||||
|
}
|
||||||
|
@ -1 +1,191 @@
|
|||||||
|
pub mod staticpair;
|
||||||
|
|
||||||
|
use super::atomic::*;
|
||||||
|
use crate::core::*;
|
||||||
|
use crate::std::*;
|
||||||
|
|
||||||
|
pub trait InlineableFactory {}
|
||||||
|
|
||||||
|
pub trait FixedSizeFactory: InlineableFactory {
|
||||||
|
fn size(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ConstSizeFactory: FixedSizeFactory {
|
||||||
|
const SIZE: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait InlineableObject<'a, Ctx: 'a + Context>: 'a {}
|
||||||
|
|
||||||
|
pub trait FixedSizeObject<'a, Ctx: 'a + Context>: InlineableObject<'a, Ctx> {
|
||||||
|
fn size(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ConstSizeObject<'a, Ctx: 'a + Context>: FixedSizeObject<'a, Ctx> {
|
||||||
|
const SIZE: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait InlineableAtomic {}
|
||||||
|
|
||||||
|
pub trait ConstSizeAtomic: InlineableAtomic {
|
||||||
|
const SIZE: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Atomic + InlineableAtomic> InlineableFactory for AtomicFactory<A> {}
|
||||||
|
|
||||||
|
impl<A: Atomic + ConstSizeAtomic> FixedSizeFactory for AtomicFactory<A> {
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
A::SIZE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Atomic + ConstSizeAtomic> ConstSizeFactory for AtomicFactory<A> {
|
||||||
|
const SIZE: usize = A::SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> InlineableObject<'a, Ctx> for A where
|
||||||
|
A::Fctr: InlineableFactory
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> FixedSizeObject<'a, Ctx> for A
|
||||||
|
where
|
||||||
|
A::Fctr: FixedSizeFactory,
|
||||||
|
{
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.factory().size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> ConstSizeObject<'a, Ctx> for A
|
||||||
|
where
|
||||||
|
A::Fctr: ConstSizeFactory,
|
||||||
|
{
|
||||||
|
const SIZE: usize = A::Fctr::SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SizeError {
|
||||||
|
expected: usize,
|
||||||
|
received: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SizeError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_fmt(format_args!(
|
||||||
|
"expected {} bytes, read/wrote {} instead.",
|
||||||
|
self.expected, self.received
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for SizeError {}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum CheckedParseError<P: Error> {
|
||||||
|
Parse(P),
|
||||||
|
Size(SizeError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Error> Display for CheckedParseError<P> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
CheckedParseError::Parse(parse_error) => f.write_fmt(format_args!("{}", parse_error)),
|
||||||
|
CheckedParseError::Size(size_error) => {
|
||||||
|
f.write_fmt(format_args!("size check failed: {}", size_error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Error> From<P> for CheckedParseError<P> {
|
||||||
|
fn from(value: P) -> Self {
|
||||||
|
Self::Parse(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type CheckedParseResult<'a, Ctx, F> =
|
||||||
|
Result<<F as Factory<'a, Ctx>>::Mtbl, CheckedParseError<<F as Factory<'a, Ctx>>::ParseError>>;
|
||||||
|
|
||||||
|
pub trait CheckedParse<'a, Ctx: 'a + Context>: FixedSizeFactory + Factory<'a, Ctx> {
|
||||||
|
fn deserialize_checked(
|
||||||
|
&self,
|
||||||
|
deserializer: &mut dyn Deserializer,
|
||||||
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
) -> CheckedParseResult<'a, Ctx, Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CheckedSerialize<'a, Ctx: 'a + Context>: Serializable + FixedSizeObject<'a, Ctx> {
|
||||||
|
fn serialize_checked(&self, serializer: &mut dyn Serializer) -> Result<(), SizeError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, F: FixedSizeFactory + Factory<'a, Ctx>> CheckedParse<'a, Ctx> for F {
|
||||||
|
fn deserialize_checked(
|
||||||
|
&self,
|
||||||
|
deserializer: &mut dyn Deserializer,
|
||||||
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
) -> CheckedParseResult<'a, Ctx, Self> {
|
||||||
|
let expected_size = self.size();
|
||||||
|
let start = deserializer.tell();
|
||||||
|
let result = self.deserialize(deserializer, resolver)?;
|
||||||
|
let end = deserializer.tell();
|
||||||
|
let received_size = end - start;
|
||||||
|
if received_size == expected_size {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(CheckedParseError::Size(SizeError {
|
||||||
|
expected: expected_size,
|
||||||
|
received: received_size,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx> + FixedSizeObject<'a, Ctx>>
|
||||||
|
CheckedSerialize<'a, Ctx> for A
|
||||||
|
{
|
||||||
|
fn serialize_checked(&self, serializer: &mut dyn Serializer) -> Result<(), SizeError> {
|
||||||
|
let expected_size = self.size();
|
||||||
|
let start = serializer.tell();
|
||||||
|
self.serialize(serializer);
|
||||||
|
let end = serializer.tell();
|
||||||
|
let received_size = end - start;
|
||||||
|
if received_size == expected_size {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(SizeError {
|
||||||
|
expected: expected_size,
|
||||||
|
received: received_size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AlwaysFixedSize {
|
||||||
|
fn _size(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: AlwaysFixedSize> InlineableFactory for F {}
|
||||||
|
|
||||||
|
impl<F: AlwaysFixedSize> FixedSizeFactory for F {
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self._size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AlwaysConstSize {
|
||||||
|
const _SIZE: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: AlwaysConstSize> AlwaysFixedSize for F {
|
||||||
|
fn _size(&self) -> usize {
|
||||||
|
Self::_SIZE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: AlwaysConstSize> ConstSizeFactory for F {
|
||||||
|
const SIZE: usize = Self::_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> AlwaysConstSize for PointFactory<F> {
|
||||||
|
const _SIZE: usize = HASH_SIZE;
|
||||||
|
}
|
||||||
|
1
src/std/inlining/staticpair.rs
Normal file
1
src/std/inlining/staticpair.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
@ -1,16 +1,19 @@
|
|||||||
//! This module introduces [`Option`]-like concepts into RADN typesystem using [`Nullable`].
|
//! This module introduces [`Option`]-like concepts into RADN typesystem using [`Nullable`].
|
||||||
|
|
||||||
|
use super::inlining::*;
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
use crate::std::*;
|
use crate::std::*;
|
||||||
|
|
||||||
/// Nullable reference type. Made for use as a linking element in data structures.
|
/// Nullable reference type. Made for use as a linking element in data structures.
|
||||||
pub enum Nullable<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
pub enum Nullable<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
||||||
|
/// Unlike original Python implementation, stores the factory only in the null case.
|
||||||
Null(A::Fctr),
|
Null(A::Fctr),
|
||||||
NotNull(Point<'a, Ctx, A>),
|
NotNull(Point<'a, Ctx, A>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Nullable reference factory.
|
/// Nullable reference factory.
|
||||||
pub struct NullableFactory<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
pub struct NullableFactory<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
||||||
|
/// Factory of the referenced object.
|
||||||
factory: A::Fctr,
|
factory: A::Fctr,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +84,7 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Factory<'a, Ctx>
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Nullable<'a, Ctx, Nullable<'a, Ctx, A>> {
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Nullable<'a, Ctx, Nullable<'a, Ctx, A>> {
|
||||||
|
/// Reduce [Nullable] nesting.
|
||||||
pub fn join(&self) -> Resolution<'a, Ctx, Nullable<'a, Ctx, A>> {
|
pub fn join(&self) -> Resolution<'a, Ctx, Nullable<'a, Ctx, A>> {
|
||||||
match self {
|
match self {
|
||||||
Nullable::Null(nullable_factory) => {
|
Nullable::Null(nullable_factory) => {
|
||||||
@ -106,3 +110,9 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Clone for Nullable<'a, Ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> AlwaysConstSize
|
||||||
|
for NullableFactory<'a, Ctx, A>
|
||||||
|
{
|
||||||
|
const _SIZE: usize = HASH_SIZE;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user