This commit is contained in:
AF 2023-04-22 18:46:22 +00:00
parent e40ea67e21
commit 4f7df3ddb5
7 changed files with 247 additions and 4 deletions

View File

@ -3,7 +3,7 @@
pub mod plain;
use std::{error::Error, marker::PhantomData, rc::Rc};
use std::marker::PhantomData;
use crate::core::*;
use crate::std::*;

View File

@ -1,7 +1,5 @@
//! [`Plain`] type for storing raw byte sequnces.
use std::fmt::Display;
use crate::std::atomic::*;
/// Raw bytes storage. Use [`Plain::raw`] to get the data.

View File

@ -1 +1,3 @@
//! Standard generic collections.
pub mod stack;

View File

@ -1,13 +1,20 @@
//! Basic implementation of a stack/linked list.
use crate::core::*;
use crate::std::inlining::*;
use crate::std::nullable::*;
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>> {
/// Reference comes first due to being inlineable.
pub rest: Stack<'a, Ctx, A>,
/// Unlike the original implementation in Python, doesn't default to using Point.
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>> {
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>>;
/// See [`StackVecWrapped`].
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>>;
/// Extention trait with helper methods for [Stack]s.
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;
/// Get the corresponding factory.
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;
/// Collect all the elements into a [`Vec`].
fn vec(self) -> StackVecWrapped<'a, Ctx, A>;
}
@ -204,3 +221,28 @@ mod tests {
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 };
}

View File

@ -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;
}

View File

@ -0,0 +1 @@

View File

@ -1,16 +1,19 @@
//! This module introduces [`Option`]-like concepts into RADN typesystem using [`Nullable`].
use super::inlining::*;
use crate::core::*;
use crate::std::*;
/// Nullable reference type. Made for use as a linking element in data structures.
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),
NotNull(Point<'a, Ctx, A>),
}
/// Nullable reference factory.
pub struct NullableFactory<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
/// Factory of the referenced object.
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>> {
/// Reduce [Nullable] nesting.
pub fn join(&self) -> Resolution<'a, Ctx, Nullable<'a, Ctx, A>> {
match self {
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;
}