use std::ops::{Add, AddAssign, Deref};
use crate::blob::{BlobEncoding, MemoryBlobStore, IntoBlob};
use crate::id::Id;
use crate::id::RawId;
use crate::patch::Entry;
use crate::patch::PATCH;
use crate::inline::encodings::hash::Handle;
use crate::inline::Inline;
use super::Trible;
use super::TribleSet;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Fragment {
exports: PATCH<16>,
facts: TribleSet,
blobs: MemoryBlobStore,
}
impl Fragment {
pub fn empty() -> Self {
Self::default()
}
pub fn rooted(root: Id, facts: TribleSet) -> Self {
let mut exports = PATCH::<16>::new();
let raw: RawId = root.into();
exports.insert(&Entry::new(&raw));
Self {
exports,
facts,
blobs: MemoryBlobStore::new(),
}
}
pub fn new<I>(exports: I, facts: TribleSet) -> Self
where
I: IntoIterator<Item = Id>,
{
let mut export_set = PATCH::<16>::new();
for id in exports {
let raw: RawId = id.into();
export_set.insert(&Entry::new(&raw));
}
Self {
exports: export_set,
facts,
blobs: MemoryBlobStore::new(),
}
}
pub fn from_facts_and_blobs(facts: TribleSet, blobs: MemoryBlobStore) -> Self {
Self {
exports: PATCH::<16>::new(),
facts,
blobs,
}
}
pub fn rooted_with_blobs(
root: Id,
facts: TribleSet,
blobs: MemoryBlobStore,
) -> Self {
let mut exports = PATCH::<16>::new();
let raw: RawId = root.into();
exports.insert(&Entry::new(&raw));
Self {
exports,
facts,
blobs,
}
}
pub fn put<S, T>(&mut self, item: T) -> Inline<Handle<S>>
where
S: BlobEncoding,
T: IntoBlob<S>,
{
self.blobs.insert(item.to_blob())
}
pub fn exports(&self) -> impl Iterator<Item = Id> + '_ {
self.exports
.iter_ordered()
.map(|raw| Id::new(*raw).expect("export ids are non-nil"))
}
pub fn root(&self) -> Option<Id> {
if self.exports.len() == 1 {
let raw = self
.exports
.iter_ordered()
.next()
.expect("len() == 1 implies a first element exists");
Some(Id::new(*raw).expect("export ids are non-nil"))
} else {
None
}
}
pub fn facts(&self) -> &TribleSet {
&self.facts
}
pub fn blobs(&self) -> &MemoryBlobStore {
&self.blobs
}
pub fn into_facts(self) -> TribleSet {
self.facts
}
pub fn into_facts_and_blobs(self) -> (TribleSet, MemoryBlobStore) {
(self.facts, self.blobs)
}
pub fn into_parts(self) -> (PATCH<16>, TribleSet, MemoryBlobStore) {
(self.exports, self.facts, self.blobs)
}
}
impl Deref for Fragment {
type Target = TribleSet;
fn deref(&self) -> &Self::Target {
&self.facts
}
}
impl<'a> IntoIterator for &'a Fragment {
type Item = &'a Trible;
type IntoIter = super::tribleset::TribleSetIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
self.facts.iter()
}
}
impl AddAssign for Fragment {
fn add_assign(&mut self, rhs: Self) {
self.facts += rhs.facts;
self.exports.union(rhs.exports);
self.blobs.union(rhs.blobs);
}
}
impl AddAssign<TribleSet> for Fragment {
fn add_assign(&mut self, rhs: TribleSet) {
self.facts += rhs;
}
}
impl Add for Fragment {
type Output = Self;
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl Add<TribleSet> for Fragment {
type Output = Self;
fn add(mut self, rhs: TribleSet) -> Self::Output {
self += rhs;
self
}
}
impl AddAssign<Fragment> for TribleSet {
fn add_assign(&mut self, rhs: Fragment) {
self.union(rhs.facts);
}
}
impl Add<Fragment> for TribleSet {
type Output = Self;
fn add(mut self, rhs: Fragment) -> Self::Output {
self += rhs;
self
}
}
impl From<TribleSet> for Fragment {
fn from(facts: TribleSet) -> Self {
Self::from_facts_and_blobs(facts, MemoryBlobStore::new())
}
}
impl From<Fragment> for TribleSet {
fn from(value: Fragment) -> Self {
value.facts
}
}