pub trait Combinator<'x, I, O>: Viewwhere
I: VestInput,
O: VestOutput<I>,
Self::V: SecureSpecCombinator<Type = <Self::Type as View>::V>,{
type Type: View;
type SType: View<V = <Self::Type as View>::V>;
// Required methods
exec fn length(&self, v: Self::SType) -> len : usize;
exec fn parse(&self, s: I) -> res : PResult<Self::Type, ParseError>;
exec fn serialize(
&self,
v: Self::SType,
buf: &mut O,
pos: usize,
) -> res : SResult<usize, SerializeError>;
// Provided method
open spec fn ex_requires(&self) -> bool { ... }
}Expand description
Implementation for parser and serializer combinators. A combinator’s view must be a
SecureSpecCombinator.
Required Associated Types§
Sourcetype SType: View<V = <Self::Type as View>::V>
type SType: View<V = <Self::Type as View>::V>
The input type of serialization, often a reference to Self::Type.
For “structural” formats though (e.g., crate::regular::sequence::Pair and crate::regular::variant::Choice),
this is the tuple/sum of the corresponding Combinator::SType types.
Required Methods§
Sourceexec fn length(&self, v: Self::SType) -> len : usize
exec fn length(&self, v: Self::SType) -> len : usize
self@.requires(),self.ex_requires(),self@.wf(v@),self@.spec_serialize(v@).len() <= usize::MAX,ensureslen == self@.spec_serialize(v@).len(),The length of the output buffer. This can be used to optimize serialization by pre-allocating the buffer.
Sourceexec fn parse(&self, s: I) -> res : PResult<Self::Type, ParseError>
exec fn parse(&self, s: I) -> res : PResult<Self::Type, ParseError>
self@.requires(),self.ex_requires(),s@.len() <= usize::MAX,ensuresres matches Ok((n, v)) ==> self@.spec_parse(s@) == Some((n as int, v@)),self@.spec_parse(s@) matches Some((n, v)) ==> res matches Ok((m, u)) && m == n && v == u@,res is Err ==> self@.spec_parse(s@) is None,self@.spec_parse(s@) is None ==> res is Err,The parsing function.
To enable “zero-copy” parsing, implementations of parse should not
consume/deepcopy the input buffer I, but rather return a slice of the
input buffer for Self::Type whenever possible.
See crate::buf_traits::VestInput and crate::buf_traits::VestPublicInput for
more details.
§Pre-conditions
§Post-conditions
Essentially, the implementation of parse is functionally correct with respect to the
specification spec_parse on both success and failure cases.
Sourceexec fn serialize(
&self,
v: Self::SType,
buf: &mut O,
pos: usize,
) -> res : SResult<usize, SerializeError>
exec fn serialize( &self, v: Self::SType, buf: &mut O, pos: usize, ) -> res : SResult<usize, SerializeError>
self@.requires(),self.ex_requires(),self@.wf(v@),pos <= old(buf)@.len() <= usize::MAX,ensuresres matches Ok(
n,
) ==> {
&&& buf@.len() == old(buf)@.len()
&&& pos <= usize::MAX - n && pos + n <= buf@.len()
&&& n == self@.spec_serialize(v@).len()
&&& buf@ == seq_splice(old(buf)@, pos, self@.spec_serialize(v@))
},The serialization function.
The intended use of serialize is to serialize a value v into the
buffer buf at the position pos “in-place” (i.e., without
allocating a new buffer or extending the buffer).
§Pre-conditions
SpecCombinator::requiresCombinator::ex_requiresSpecCombinator::wfposis less than or equal to the length of the buffer, whose length is less than or equal tousize::MAX.
§Post-conditions
serialize ensures that it is functionally correct with respect to the
specification spec_serialize when it returns Ok. This is because
serialize being a partial function can fail (e.g.,
insufficient buffer space), while spec_serialize is a
total function (with infinite buffer size) and will never fail.
Provided Methods§
Sourceopen spec fn ex_requires(&self) -> bool
open spec fn ex_requires(&self) -> bool
{ true }Additional pre-conditions for parsing and serialization
e.g., crate::regular::sequence::Pair combinator requires that the
crate::regular::sequence::Continuation is well-formed w.r.t. the
spec_fn closure.
Implementations on Foreign Types§
Source§impl<'x, Fst, Snd, I, O> Combinator<'x, I, O> for (Fst, Snd)where
I: VestInput,
O: VestOutput<I>,
Fst: Combinator<'x, I, O>,
Snd: Combinator<'x, I, O>,
Fst::V: SecureSpecCombinator<Type = <Fst::Type as View>::V>,
Snd::V: SecureSpecCombinator<Type = <Snd::Type as View>::V>,
impl<'x, Fst, Snd, I, O> Combinator<'x, I, O> for (Fst, Snd)where
I: VestInput,
O: VestOutput<I>,
Fst: Combinator<'x, I, O>,
Snd: Combinator<'x, I, O>,
Fst::V: SecureSpecCombinator<Type = <Fst::Type as View>::V>,
Snd::V: SecureSpecCombinator<Type = <Snd::Type as View>::V>,
Source§open spec fn ex_requires(&self) -> bool
open spec fn ex_requires(&self) -> bool
{ self.0.ex_requires() && self.1.ex_requires() }