atomic_lib 0.41.0-beta.3

Library for creating, storing, querying, validating and converting Atomic Data.
Documentation
//! The smallest units of data, consisting of a Subject, a Property and a Value

use crate::{
    errors::AtomicResult,
    values::{ReferenceString, SortableValue, Value},
    Subject,
};

/// The Atom is the smallest meaningful piece of data.
/// It describes how one value relates to a subject.
/// A [Resource] can be converted into a bunch of Atoms.
#[derive(Clone, Debug)]
pub struct Atom {
    /// The URL where the resource is located
    pub subject: Subject,
    pub property: String,
    pub value: Value,
}

impl Atom {
    pub fn new(subject: Subject, property: String, value: Value) -> Self {
        Atom {
            subject,
            property,
            value,
        }
    }

    /// If the Atom's Value is an Array, this will try to convert it into a set of Subjects.
    /// Used for indexing.
    pub fn values_to_subjects(&self) -> AtomicResult<Vec<String>> {
        let base_path = format!("{} {}", self.subject, self.property);
        self.value.to_subjects(Some(base_path))
    }

    /// Converts one Atom to a series of stringified values that can be indexed.
    pub fn to_indexable_atoms(&self) -> Vec<IndexAtom> {
        // Using sort_value causes issues but we really need to look at how to do this properly.
        // let sort_value = self.value.to_sortable_string();
        let index_atoms: Vec<IndexAtom> = match &self.value.to_reference_index_strings() {
            Some(v) => {
                tracing::trace!(
                    "to_indexable_atoms: found {} reference strings for property {}",
                    v.len(),
                    self.property
                );
                v.iter()
                    .map(|v| IndexAtom {
                        ref_value: v.into(),
                        sort_value: v.into(),
                        subject: self.subject.clone(),
                        property: self.property.clone(),
                    })
                    .collect()
            }
            None => {
                tracing::trace!(
                    "to_indexable_atoms: no reference strings for property {}",
                    self.property
                );
                vec![]
            }
        };
        index_atoms
    }
}

/// Differs from a regular [Atom], since the value here is always a string,
/// and in the case of ResourceArrays, only a _single_ subject is used for each atom.
/// One IndexAtom for every member of the ResourceArray is created.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IndexAtom {
    pub subject: Subject,
    pub property: String,
    pub ref_value: ReferenceString,
    pub sort_value: SortableValue,
}

impl std::fmt::Display for Atom {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.write_str(&format!(
            "<{}> <{}> '{}'",
            self.subject, self.property, self.value
        ))?;
        Ok(())
    }
}