1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! This module allows to describe a primitive subset of [Mentionable] types, [Atomic]s,
//! simple static types, which are completely [Context]-independent.
//!
//! [Mentionable]: crate::rcore::Mentionable
//! [Context]: crate::rcore::Context

mod inlining;
mod modes;
mod regular;

use std::error::Error;

use crate::mode::*;

pub use self::inlining::{AIParseResult, CInliningAtomic, InliningAtomic};
pub use self::modes::{
    AExtensionResultM, AExtensionSourceM, AModeResultM, AtomicModeParse, AtomicModeProxy,
};
pub use self::regular::{CRegularAtomic, RegularAtomic};

/// [`Atomic`] version of [`ParseError`].
///
/// [`ParseError`]: crate::rcore::ParseError
pub type AParseError<A> = <A as AtomicBase>::AParseError;

/// [`Atomic`] version of [`ParseResult`]
///
/// [`ParseResult`]: crate::rcore::ParseResult
pub type AParseResult<A> = Result<A, AParseError<A>>;

/// [`Atomic`] base.
pub trait AtomicBase: 'static + Send + Sync + Clone + Serializable {
    /// Equivalent of [`FactoryBase::ParseError`].
    ///
    /// [`FactoryBase::ParseError`]: crate::rcore::FactoryBase::ParseError
    type AParseError: Error + Send;
}

/// This trait combines functionality of [`Mentionable`] and [`Factory`],
/// while limiting [`MentionableTop::points_typed`] (and corresponding [`MentionableTop::topology_hash`])
/// to an empty sequence.
///
/// [`Mentionable`]: crate::rcore::Mentionable
/// [`Factory`]: crate::rcore::Factory
/// [`MentionableTop::points_typed`]: crate::rcore::MentionableTop::points_typed
/// [`MentionableTop::topology_hash`]: crate::rcore::MentionableTop::topology_hash
pub trait Atomic: AtomicModeParse {
    /// Static equivalent of [`FactoryParse::deserialize`].
    ///
    /// [`FactoryParse::deserialize`]: crate::rcore::FactoryParse::deserialize
    fn a_deserialize(stream: impl Stream) -> AParseResult<Self>;

    /// Static equivalent of [`FactoryParse::extend`].
    ///
    /// [`FactoryParse::extend`]: crate::rcore::FactoryParse::extend
    fn a_extend(self, tail: &[u8]) -> AParseResult<Self>;
}

fn parse_slice<A: Atomic>(slice: &[u8]) -> AParseResult<A> {
    let mut deserializer = SliceDeserializer::from(slice);
    let atomic = A::a_deserialize(&mut deserializer)?;
    let tail = deserializer.read_all();
    if tail.is_empty() {
        Ok(atomic)
    } else {
        atomic.a_extend(tail)
    }
}

/// Extension trait to provide method-like utilities associated with [Atomic]s.
pub trait AtomicExt: Atomic {
    /// Static equivalent of [`FactoryExt::parse_slice`].
    ///
    /// [`FactoryExt::parse_slice`]: crate::rcore::FactoryExt::parse_slice
    fn parse_slice(slice: &[u8]) -> AParseResult<Self> {
        parse_slice(slice)
    }
}

impl<A: Atomic> AtomicExt for A {}