use datasize::DataSize;
use minicbor::{Decode, Encode};
use sealed::sealed;
use serde::ser::{SerializeSeq, SerializeStruct, Serializer};
use serde::{Deserialize, Serialize};
use crate::annotationdataset::{AnnotationDataSet, AnnotationDataSetHandle};
use crate::datakey::{DataKey, DataKeyHandle};
use crate::datavalue::DataValue;
use crate::error::StamError;
use crate::store::*;
use crate::types::*;
#[derive(Debug, Clone, DataSize, Encode, Decode)]
pub struct AnnotationData {
#[n(0)]
pub(crate) intid: Option<AnnotationDataHandle>,
#[n(1)]
pub(crate) id: Option<String>,
#[n(2)]
pub(crate) key: DataKeyHandle,
#[n(3)]
value: DataValue,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, DataSize, Encode, Decode)]
#[cbor(transparent)]
pub struct AnnotationDataHandle(#[n(0)] u32);
#[sealed]
impl Handle for AnnotationDataHandle {
fn new(intid: usize) -> Self {
Self(intid as u32)
}
fn as_usize(&self) -> usize {
self.0 as usize
}
}
impl<'a> Request<AnnotationData> for AnnotationDataHandle {
fn to_handle<'store, S>(&self, _store: &'store S) -> Option<AnnotationDataHandle>
where
S: StoreFor<AnnotationData>,
{
Some(*self)
}
}
impl From<AnnotationDataHandle> for BuildItem<'_, AnnotationData> {
fn from(handle: AnnotationDataHandle) -> Self {
Self::Handle(handle)
}
}
impl From<&AnnotationDataHandle> for BuildItem<'_, AnnotationData> {
fn from(handle: &AnnotationDataHandle) -> Self {
Self::Handle(*handle)
}
}
#[sealed]
impl TypeInfo for AnnotationData {
fn typeinfo() -> Type {
Type::AnnotationData
}
}
#[sealed]
impl Storable for AnnotationData {
type HandleType = AnnotationDataHandle;
type StoreHandleType = AnnotationDataSetHandle;
type FullHandleType = (AnnotationDataSetHandle, AnnotationDataHandle);
type StoreType = AnnotationDataSet;
fn handle(&self) -> Option<AnnotationDataHandle> {
self.intid
}
fn id(&self) -> Option<&str> {
self.id.as_deref()
}
fn with_handle(mut self, intid: AnnotationDataHandle) -> Self {
self.intid = Some(intid);
self
}
fn with_id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
fn carries_id() -> bool {
true
}
fn fullhandle(
storehandle: Self::StoreHandleType,
handle: Self::HandleType,
) -> Self::FullHandleType {
(storehandle, handle)
}
fn merge(&mut self, other: Self) -> Result<(), StamError> {
let intid = self.intid;
*self = other;
self.intid = intid; Ok(())
}
fn unbind(mut self) -> Self {
self.intid = None;
self
}
}
impl PartialEq<AnnotationData> for AnnotationData {
fn eq(&self, other: &AnnotationData) -> bool {
self.id.is_some()
&& self.id == other.id
&& self.key == other.key
&& self.value == other.value
}
}
impl<'a> Serialize for ResultItem<'a, AnnotationData> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("AnnotationData", 2)?;
state.serialize_field("@type", "AnnotationData")?;
if let Some(id) = self.id() {
state.serialize_field("@id", id)?;
} else {
state.serialize_field(
"@id",
&self.as_ref().temp_id().expect("temp_id must succeed"),
)?;
}
let keyhandle = self.as_ref().key();
let key = self.store().get(keyhandle).expect("key must exist");
state.serialize_field("key", &key.id())?;
state.serialize_field("value", self.as_ref().value())?;
state.end()
}
}
#[allow(dead_code)] pub(crate) struct AnnotationDataRefImpliedSet<'a>(pub(crate) ResultItem<'a, AnnotationData>);
impl<'a> Serialize for AnnotationDataRefImpliedSet<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("AnnotationData", 2)?;
state.serialize_field("@type", "AnnotationData")?;
if let Some(id) = self.0.id() {
state.serialize_field("@id", id)?;
} else {
state.serialize_field(
"@id",
&self.0.as_ref().temp_id().expect("temp_id must succeed"),
)?;
}
state.serialize_field("key", &self.0.key().id())?;
state.serialize_field("value", self.0.as_ref().value())?;
state.end()
}
}
impl<'a> Serialize for WrappedStore<'a, AnnotationData, AnnotationDataSet> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.store.len()))?;
for data in self.store.iter() {
if let Some(data) = data {
seq.serialize_element(&ResultItem::new_partial(data, self.parent))?;
}
}
seq.end()
}
}
impl AnnotationData {
pub(crate) fn new(id: Option<String>, key: DataKeyHandle, value: DataValue) -> Self {
AnnotationData {
id,
key,
value,
intid: None,
}
}
pub fn key(&self) -> DataKeyHandle {
self.key
}
pub fn value(&self) -> &DataValue {
&self.value
}
pub fn to_json(&self, store: &AnnotationDataSet) -> Result<String, StamError> {
let resultitem: ResultItem<Self> = ResultItem::new_partial(self, store);
serde_json::to_string_pretty(&resultitem).map_err(|e| {
StamError::SerializationError(format!("Writing annotation dataset to string: {}", e))
})
}
}
#[derive(Deserialize, Clone, Debug)]
#[serde(tag = "AnnotationData")]
#[serde(from = "AnnotationDataJson")]
pub struct AnnotationDataBuilder<'a> {
#[serde(rename = "@id")]
pub(crate) id: BuildItem<'a, AnnotationData>,
#[serde(rename = "set")]
pub(crate) dataset: BuildItem<'a, AnnotationDataSet>,
pub(crate) key: BuildItem<'a, DataKey>,
pub(crate) value: DataValue,
}
impl<'a> Default for AnnotationDataBuilder<'a> {
fn default() -> Self {
Self {
id: BuildItem::None,
dataset: BuildItem::None,
key: BuildItem::None,
value: DataValue::Null,
}
}
}
impl<'a> AnnotationDataBuilder<'a> {
pub fn new() -> Self {
Self::default()
}
pub fn with_id(mut self, id: BuildItem<'a, AnnotationData>) -> Self {
self.id = id;
self
}
pub fn id(&self) -> &BuildItem<'_, AnnotationData> {
&self.id
}
pub fn with_dataset(mut self, dataset: BuildItem<'a, AnnotationDataSet>) -> Self {
self.dataset = dataset;
self
}
pub fn dataset(&self) -> &BuildItem<'_, AnnotationDataSet> {
&self.dataset
}
pub fn with_key(mut self, key: BuildItem<'a, DataKey>) -> Self {
self.key = key;
self
}
pub fn key(&self) -> &BuildItem<'_, DataKey> {
&self.key
}
pub fn with_value(mut self, value: DataValue) -> Self {
self.value = value;
self
}
pub fn value(&self) -> &DataValue {
&self.value
}
}
#[derive(Deserialize)]
pub(crate) struct AnnotationDataJson {
#[serde(rename = "@id")]
id: Option<String>,
set: Option<String>,
key: Option<String>,
value: Option<DataValue>,
}
impl<'a> From<AnnotationDataJson> for AnnotationDataBuilder<'a> {
fn from(helper: AnnotationDataJson) -> Self {
Self {
id: helper.id.into(),
dataset: helper.set.into(),
key: helper.key.into(),
value: helper.value.unwrap_or(DataValue::Null),
}
}
}