pub struct LiveStream(/* private fields */);
stream
only.Expand description
Stateful stream object initialized against some Database
.
While this type can be provided directly to methods such as
Scratch::scan_sync_stream()
, the other structs in this module wrap it in
a type-erased Handle
as a way to swap out whether lazy or eager cloning
strategies are used.
Implementations§
Source§impl LiveStream
§Stream Operations
After creation, the stream can be written to, but doing so
requires providing an additional match callback, which is the job of structs
like ScratchStreamSink
. Instead, this struct provides Self::reset()
and Self::compress()
to modify or serialize the instantaneous stream
state, neither of which require invoking a match callback.
impl LiveStream
§Stream Operations
After creation, the stream can be written to, but doing so
requires providing an additional match callback, which is the job of structs
like ScratchStreamSink
. Instead, this struct provides Self::reset()
and Self::compress()
to modify or serialize the instantaneous stream
state, neither of which require invoking a match callback.
Sourcepub fn open(db: &Database) -> Result<Self, VectorscanRuntimeError>
pub fn open(db: &Database) -> Result<Self, VectorscanRuntimeError>
Initialize a new live stream object into a newly allocated memory region.
The stream will be set to the initial automaton state, with match offsets starting at 0.
Sourcepub fn reset(&mut self) -> Result<(), VectorscanRuntimeError>
pub fn reset(&mut self) -> Result<(), VectorscanRuntimeError>
Reset this stream’s automaton state to the initial state, and restart match offsets at 0.
Sourcepub fn compress(
&self,
into: CompressReserveBehavior,
) -> Result<CompressedStream, CompressionError>
pub fn compress( &self, into: CompressReserveBehavior, ) -> Result<CompressedStream, CompressionError>
Write the stream’s current state into a buffer according to the into
strategy using CompressedStream::compress()
.
The stream can later be deserialized from this state into a working
in-memory stream again with methods such as
CompressedStream::expand()
.
Source§impl LiveStream
§Managing Allocations
These methods provide access to the underlying memory allocation containing
the data for the in-memory stream. They can be used along with
CompressedStream::expand_into_at()
to control the memory
location used for the stream, or to preserve stream allocations across
weird lifetime constraints.
impl LiveStream
§Managing Allocations
These methods provide access to the underlying memory allocation containing
the data for the in-memory stream. They can be used along with
CompressedStream::expand_into_at()
to control the memory
location used for the stream, or to preserve stream allocations across
weird lifetime constraints.
Note that Database::stream_size()
can be used to determine the size of
the memory allocation pointed to by Self::as_ref_native()
and
Self::as_mut_native()
, but (FIXME?) there is currently no method
provided by the vectorscan library to get the stream’s allocation size from
the stream object itself.
Sourcepub const unsafe fn from_native(p: *mut NativeStream) -> Self
pub const unsafe fn from_native(p: *mut NativeStream) -> Self
Wrap the provided allocation p
.
§Safety
The pointer p
must point to an initialized db allocation prepared by
Self::open()
or CompressedStream::expand_into_at()
!
This method also makes it especially easy to create multiple references to
the same allocation, which will then cause a double free when
Self::try_drop()
is called more than once for the same db allocation.
To avoid that issue, you can wrap the result in a
ManuallyDrop
; but
unlike Database::from_native()
, a stream is a mutable object, so
multiple copies of it will break Rust’s ownership rules:
#[cfg(feature = "compiler")]
fn main() -> Result<(), vectorscan::error::VectorscanError> {
use vectorscan::{expression::*, flags::*, matchers::*, stream::*};
use std::{mem::ManuallyDrop, ops::Range};
// Compile a legitimate stream:
let expr: Expression = "a+".parse()?;
let db = expr.compile(
Flags::SOM_LEFTMOST,
Mode::STREAM | Mode::SOM_HORIZON_LARGE
)?;
let mut scratch = db.allocate_scratch()?;
let mut stream = db.allocate_stream()?;
// Create two new references to that allocation,
// wrapped to avoid calling the drop code:
let stream_ptr: *mut NativeStream = stream.as_mut_native();
let mut stream_ref_1 = ManuallyDrop::new(unsafe { LiveStream::from_native(stream_ptr) });
let mut stream_ref_2 = ManuallyDrop::new(unsafe { LiveStream::from_native(stream_ptr) });
// Both stream references are valid and can be used for matching.
let mut matches: Vec<Range<usize>> = Vec::new();
let mut match_fn = |StreamMatch { range, .. }| {
matches.push(range.into());
MatchResult::Continue
};
let mut matcher = StreamMatcher::new(&mut match_fn);
scratch
.scan_sync_stream(&mut stream_ref_1, &mut matcher, "aardvarka".into())?;
scratch
.scan_sync_stream(&mut stream_ref_2, &mut matcher, "aardvarka".into())?;
// The 8..11 demonstrates that this was actually the same mutable stream!
assert_eq!(&matches, &[0..1, 0..2, 5..6, 8..9, 8..10, 8..11, 14..15, 17..18]);
Ok(())
}
Sourcepub fn as_ref_native(&self) -> &NativeStream
pub fn as_ref_native(&self) -> &NativeStream
Get a read-only reference to the stream allocation.
This method is mostly used internally and cast to a pointer to provide to the vectorscan native library methods.
Sourcepub fn as_mut_native(&mut self) -> &mut NativeStream
pub fn as_mut_native(&mut self) -> &mut NativeStream
Get a mutable reference to the stream allocation.
The result of this method can be cast to a pointer and provided to
Self::from_native()
.
Sourcepub fn try_clone(&self) -> Result<Self, VectorscanRuntimeError>
pub fn try_clone(&self) -> Result<Self, VectorscanRuntimeError>
Generate a new stream in a newly allocated memory region which matches the same db.
The stream will be set to the initial automaton state.
Sourcepub unsafe fn try_clone_from(
&mut self,
source: &Self,
) -> Result<(), VectorscanRuntimeError>
pub unsafe fn try_clone_from( &mut self, source: &Self, ) -> Result<(), VectorscanRuntimeError>
Reset the stream state to the same as that of source
.
§Safety
self
and source
must have been originally opened against the same db
(meaning the same compiled database, not necessarily the same db
allocation)!
Sourcepub unsafe fn try_drop(&mut self) -> Result<(), VectorscanRuntimeError>
pub unsafe fn try_drop(&mut self) -> Result<(), VectorscanRuntimeError>
Free the underlying stream allocation.
§Safety
This method must be called at most once over the lifetime of each stream
allocation. It is called by default on drop, so
ManuallyDrop
is recommended to wrap instances
that reference external data in order to avoid attempting to free the
referenced data.
§Only Frees Memory
This method performs no processing other than freeing the allocated
memory, so it can be skipped without leaking resources if the
underlying NativeStream
allocation is freed by some other means.
Trait Implementations§
Source§impl Clone for LiveStream
NB: Clone::clone_from()
is not implemented because
Self::try_clone_from()
is unsafe!
impl Clone for LiveStream
NB: Clone::clone_from()
is not implemented because
Self::try_clone_from()
is unsafe!
Source§impl Debug for LiveStream
impl Debug for LiveStream
Source§impl Drop for LiveStream
impl Drop for LiveStream
Source§impl Resource for LiveStream
impl Resource for LiveStream
Source§type Error = VectorscanRuntimeError
type Error = VectorscanRuntimeError
Source§fn deep_clone(&self) -> Result<Self, Self::Error>
fn deep_clone(&self) -> Result<Self, Self::Error>
self
.Source§fn deep_boxed_clone(
&self,
) -> Result<Box<dyn Resource<Error = Self::Error>>, Self::Error>
fn deep_boxed_clone( &self, ) -> Result<Box<dyn Resource<Error = Self::Error>>, Self::Error>
Self::deep_clone()
, but places the concrete type in a
heap-allocated box. Read moreimpl Send for LiveStream
Auto Trait Implementations§
impl Freeze for LiveStream
impl RefUnwindSafe for LiveStream
impl !Sync for LiveStream
impl Unpin for LiveStream
impl UnwindSafe for LiveStream
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<R> Handle for Rwhere
R: Resource,
impl<R> Handle for Rwhere
R: Resource,
Source§type R = R
type R = R
Source§fn wrap(r: <R as Handle>::R) -> R
fn wrap(r: <R as Handle>::R) -> R
Source§fn clone_handle(&self) -> Result<R, <<R as Handle>::R as Resource>::Error>
fn clone_handle(&self) -> Result<R, <<R as Handle>::R as Resource>::Error>
Source§fn boxed_clone_handle(
&self,
) -> Result<Box<dyn Handle<R = <R as Handle>::R>>, <<R as Handle>::R as Resource>::Error>
fn boxed_clone_handle( &self, ) -> Result<Box<dyn Handle<R = <R as Handle>::R>>, <<R as Handle>::R as Resource>::Error>
Self::clone_handle()
, but places the concrete type in a
heap-allocated box.Source§fn handle_ref(&self) -> &<R as Handle>::R
fn handle_ref(&self) -> &<R as Handle>::R
Source§fn ensure_exclusive(
&mut self,
) -> Result<(), <<R as Handle>::R as Resource>::Error>
fn ensure_exclusive( &mut self, ) -> Result<(), <<R as Handle>::R as Resource>::Error>
Source§fn eq_ref(&self, other: &(dyn Handle<R = Self::R> + 'static)) -> bool
fn eq_ref(&self, other: &(dyn Handle<R = Self::R> + 'static)) -> bool
Source§fn make_mut(&mut self) -> Result<&mut Self::R, <Self::R as Resource>::Error>
fn make_mut(&mut self) -> Result<&mut Self::R, <Self::R as Resource>::Error>
Self::ensure_exclusive()
and Self::get_mut()
.