simple-triplestore 0.1.1

A simple graph database for storing triples with support for custom node and edge properties.
Documentation
use std::sync::{
    atomic::{AtomicU64, Ordering},
    Arc,
};

use crate::{traits::IdGenerator, traits::IdType, Triple};

impl IdType for u64 {
    type ByteArrayType = [u8; 8];
    type TripleByteArrayType = [u8; 24];

    fn to_be_bytes(self) -> Self::ByteArrayType {
        self.to_be_bytes()
    }

    fn from_be_bytes(bytes: &Self::ByteArrayType) -> Self {
        u64::from_be_bytes(*bytes)
    }

    fn try_from_be_bytes(bytes: &[u8]) -> Option<Self> {
        bytes
            .try_into()
            .map(|bytes: &Self::ByteArrayType| Some(u64::from_be_bytes(*bytes)))
            .unwrap_or(None)
    }

    fn encode_spo_triple(triple: &Triple<Self>) -> Self::TripleByteArrayType {
        let mut data = [0u8; 24];
        data[0..8].copy_from_slice(&triple.sub.to_be_bytes());
        data[8..16].copy_from_slice(&triple.pred.to_be_bytes());
        data[16..24].copy_from_slice(&triple.obj.to_be_bytes());
        data
    }

    fn encode_pos_triple(triple: &Triple<Self>) -> Self::TripleByteArrayType {
        let mut data = [0u8; 24];
        data[0..8].copy_from_slice(&triple.pred.to_be_bytes());
        data[8..16].copy_from_slice(&triple.obj.to_be_bytes());
        data[16..24].copy_from_slice(&triple.sub.to_be_bytes());
        data
    }

    fn encode_osp_triple(triple: &Triple<Self>) -> Self::TripleByteArrayType {
        let mut data = [0u8; 24];
        data[0..8].copy_from_slice(&triple.obj.to_be_bytes());
        data[8..16].copy_from_slice(&triple.sub.to_be_bytes());
        data[16..24].copy_from_slice(&triple.pred.to_be_bytes());
        data
    }

    fn decode_spo_triple(data: &Self::TripleByteArrayType) -> Triple<Self> {
        let sub = Self::from_be_bytes(data[0..8].try_into().unwrap());
        let pred = Self::from_be_bytes(data[8..16].try_into().unwrap());
        let obj = Self::from_be_bytes(data[16..24].try_into().unwrap());
        Triple { sub, pred, obj }
    }

    fn decode_pos_triple(data: &Self::TripleByteArrayType) -> Triple<Self> {
        let pred = Self::from_be_bytes(data[0..8].try_into().unwrap());
        let obj = Self::from_be_bytes(data[8..16].try_into().unwrap());
        let sub = Self::from_be_bytes(data[16..24].try_into().unwrap());
        Triple { sub, pred, obj }
    }

    fn decode_osp_triple(data: &Self::TripleByteArrayType) -> Triple<Self> {
        let obj = Self::from_be_bytes(data[0..8].try_into().unwrap());
        let sub = Self::from_be_bytes(data[8..16].try_into().unwrap());
        let pred = Self::from_be_bytes(data[16..24].try_into().unwrap());
        Triple { sub, pred, obj }
    }

    fn key_bounds_1(
        a: Self,
    ) -> (
        std::ops::Bound<Self::TripleByteArrayType>,
        std::ops::Bound<Self::TripleByteArrayType>,
    ) {
        (
            std::ops::Bound::Included(Self::encode_spo_triple(&Triple {
                sub: a,
                pred: u64::MIN,
                obj: u64::MIN,
            })),
            std::ops::Bound::Included(Self::encode_spo_triple(&Triple {
                sub: a,
                pred: u64::MAX,
                obj: u64::MAX,
            })),
        )
    }

    fn key_bounds_2(
        a: Self,
        b: Self,
    ) -> (
        std::ops::Bound<Self::TripleByteArrayType>,
        std::ops::Bound<Self::TripleByteArrayType>,
    ) {
        (
            std::ops::Bound::Included(Self::encode_spo_triple(&Triple {
                sub: a,
                pred: b,
                obj: u64::MIN,
            })),
            std::ops::Bound::Included(Self::encode_spo_triple(&Triple {
                sub: a,
                pred: b,
                obj: u64::MAX,
            })),
        )
    }
}

struct U64IdGenerator {
    state: Arc<AtomicU64>,
}

impl U64IdGenerator {
    pub fn new(initial_value: u64) -> Self {
        Self {
            state: Arc::new(AtomicU64::new(initial_value)),
        }
    }
}

impl IdGenerator<u64> for U64IdGenerator {
    fn clone(&self) -> Box<dyn IdGenerator<u64>> {
        Box::new(Self {
            state: self.state.clone(),
        })
    }

    fn fresh(&mut self) -> u64 {
        self.state.fetch_add(1, Ordering::SeqCst)
    }
}