Expand description
Blob support.
Blobs are a way to share data with SWI-Prolog which does not fit in any one of the built-in term types. They are stored in the SWI-Prolog environment as a special kind of atom.
This module, together with the various blob macros, implement support for different classes of blobs.
For all blob types, macros have been defined to easily define and implement them. This allows your type to be used with Term::get, Term::put, and Term::unify.
ArcBlob
This type of blob is a pointer to atomically reference counted rust data. Upon getting, putting or unifying terms with data of this type, only the pointer is transfered and reference counts are updated.
Examples
Using the default implementation for write
and compare
:
// note the keyword 'defaults' below - this makes sure that a
// default implementation of `ArcBlobImpl` is generated.
#[arc_blob("foo", defaults)]
struct Foo {
num: u64
}
fn do_something(term1: &Term, term2: &Term) -> PrologResult<()> {
let arc = Arc::new(Foo{num: 42});
term1.unify(&arc)?;
let retrieved: Arc<Foo> = term1.get()?;
assert_eq!(42, retrieved.num);
term2.put(&retrieved)?;
Ok(())
}
Provide your own implementation for write
and compare
:
#[arc_blob("foo")]
struct Foo {
num: u64
}
impl ArcBlobImpl for Foo {
fn write(&self, stream: &mut PrologStream) -> std::io::Result<()> {
write!(stream, "<foo {}>", self.num)
}
fn compare(&self, other: &Self) -> Ordering {
self.num.cmp(&other.num)
}
}
WrappedArcBlob
This type of blob is very similar to an ArcBlob. The difference
is that it is wrapped in a struct. This is done due to the
requirement that a trait from another crate can only be
implemented for your own types. This means that ArcBlob cannot
be directly implemented from code that depends on the swipl
crate for an Arc
that comes out of another dependency. The
wrapper allows a trait to be implemented that does the job.
Examples
Using the default implementation for write
and compare
:
// Note that it is not possible to implement ArcBlob directly on a
// Vec<bool>, as it is not a type defined by us. That's why it
// needs to be wrapped.
wrapped_arc_blob!("foo", Foo, Vec<bool>, defaults);
fn do_something(term1: &Term, term2: &Term) -> PrologResult<()> {
let wrapped = Foo(Arc::new(vec![true,false,true]));
term1.unify(&wrapped)?;
let retrieved: Foo = term1.get()?;
assert!(!retrieved[1]);
term2.put(&retrieved)?;
Ok(())
}
Provide your own implementation for write
and compare
:
wrapped_arc_blob!("foo", Foo, Vec<bool> );
impl WrappedArcBlobImpl for Foo {
fn write(this: &Vec<bool>, stream: &mut PrologStream) -> std::io::Result<()> {
write!(stream, "<foo {:?}>",this)
}
fn compare(this: &Vec<bool>, other: &Vec<bool>) -> Ordering {
this.cmp(other)
}
}
CloneBlob
This type of blob copies its contents to and from SWI-Prolog when getting, putting or unifying terms with the data.
Examples
// note the keyword 'defaults' below - this makes sure that a
// default implementation of `CloneBlobImpl` is generated.
// note also that the struct below derives Clone, which allows it
// to be used as a clone blob.
#[clone_blob("foo", defaults)]
#[derive(Clone)]
struct Foo {
num: u64
}
fn do_something(term1: &Term, term2: &Term) -> PrologResult<()> {
let val = Foo{num: 42};
term1.unify(&val)?;
let retrieved: Foo = term1.get()?;
assert_eq!(42, retrieved.num);
term2.put(&retrieved)?;
Ok(())
}
Provide your own implementation for write
and compare
:
#[clone_blob("foo")]
#[derive(Clone)]
struct Foo {
num: u64
}
impl CloneBlobImpl for Foo {
fn write(&self, stream: &mut PrologStream) -> std::io::Result<()> {
write!(stream, "<foo {}>", self.num)
}
fn compare(&self, other: &Self) -> Ordering {
self.num.cmp(&other.num)
}
}
wrapped CloneBlob
For convenience, there’s also a
wrapped_clone_blob! macro
for cases where we wish to generate a blob out of cloneable data
that is of a type defined in another crate. This is analogous to
the wrapped arc blob, except that no extra types are
required. There is no WrappedCloneBlob
, instead, the wrapper
just implements CloneBlob directly.
Examples
wrapped_clone_blob!("foo", Foo, Vec<bool>, defaults);
fn do_something(term1: &Term, term2: &Term) -> PrologResult<()> {
let val = Foo(vec![true, false, true]);
term1.unify(&val)?;
let retrieved: Foo = term1.get()?;
assert!(!retrieved[1]);
term2.put(&retrieved)?;
Ok(())
}
Provide your own implementation for write
and compare
:
wrapped_clone_blob!("foo", Foo, Vec<bool>);
impl CloneBlobImpl for Foo {
fn write(&self, stream: &mut PrologStream) -> std::io::Result<()> {
write!(stream, "<foo {:?}>", self.0)
}
fn compare(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
Traits
- A blob type whose data is shared with SWI-Prolog as an atomic reference-counted pointer.
- Base type for ArcBlob.
- A blob type whose data is copied into SWI-Prolog and dropped on garbage collection.
- Base type for CloneBlob.
- A blob type whose data is shared with SWI-Prolog as an atomic reference-counted pointer, and which is wrapped into a wrapper type.
- Base type for WrappedArcBlob.
Functions
- Increment the reference count on an Arc stored in a blob.
- Create a blob definition for use with the SWI-Prolog fli out of the given components.
- Retrieve an arc from the given term, using the given blob definition.
- Retrieve a cloneable value from the given term, using the given blob definition.
- Put an arc into the given term, using the given blob definition.
- Put a Cloneable into the given term, using the given blob definition.
- Decrement the reference count on an Arc stored in a blob.
- Drop the rust value stored in a blob.
- Unify the term with the given
Arc
, using the given blob definition to do so. - Unify the term with the given Cloneable, using the given blob definition to do so.