use crate::{DataError, Statement, StatementId, validate_irl};
use core::fmt;
use iri_string::types::{IriStr, IriString};
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use tracing::warn;
#[skip_serializing_none]
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct StatementResult {
statements: Vec<Statement>,
more: Option<IriString>,
}
#[skip_serializing_none]
#[derive(Debug, Serialize)]
pub struct StatementResultId {
statements: Vec<StatementId>,
more: Option<IriString>,
}
impl From<StatementResult> for StatementResultId {
fn from(value: StatementResult) -> Self {
StatementResultId {
statements: value
.statements
.into_iter()
.map(StatementId::from)
.collect(),
more: value.more,
}
}
}
impl StatementResult {
pub fn from(statements: Vec<Statement>) -> Self {
StatementResult {
statements,
more: None,
}
}
pub fn statements(&self) -> &Vec<Statement> {
self.statements.as_ref()
}
pub fn is_empty(&self) -> bool {
self.statements.is_empty()
}
pub fn more(&self) -> Option<&IriStr> {
self.more.as_deref()
}
pub fn set_more(&mut self, val: &str) -> Result<(), DataError> {
let s = val.trim();
if s.is_empty() {
warn!("Input value is empty. Unset URL");
self.more = None;
} else {
let iri = IriStr::new(s)?;
validate_irl(iri)?;
self.more = Some(iri.to_owned());
}
Ok(())
}
}
impl fmt::Display for StatementResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let statements = self
.statements
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ");
if let Some(z_more) = self.more.as_ref() {
write!(f, "StatementResult{{[ {} ], '{}'}}", statements, z_more)
} else {
write!(f, "StatementResult{{[ {statements} ]}}")
}
}
}
impl StatementResultId {
pub fn from(statements: Vec<StatementId>) -> Self {
StatementResultId {
statements,
more: None,
}
}
pub fn set_more(&mut self, val: &str) -> Result<(), DataError> {
let s = val.trim();
let iri = IriStr::new(s)?;
self.more = Some(iri.to_owned());
Ok(())
}
pub fn is_empty(&self) -> bool {
self.statements.is_empty()
}
pub fn statements(&self) -> &Vec<StatementId> {
self.statements.as_ref()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialization() {
const SR: &str = r#"{
"statements":[{
"id":"01932d1e-a584-79d2-b83a-6b380546b21c",
"actor":{"mbox":"mailto:agent99@adlnet.gov"},
"verb":{"id":"http://adlnet.gov/expapi/verbs/attended"},
"object":{
"objectType":"SubStatement",
"actor":{"objectType":"Group","member":[],"mbox":"mailto:groupb@adlnet.gov"},
"verb":{"id":"http://adlnet.gov/expapi/verbs/attended"},
"object":{"id":"http://www.example.com/unicode/36c47486-83c8-4b4f-872c-67af87e9ad10"},
"timestamp":"2024-11-20T00:06:06.838Z"
},
"timestamp":"2024-11-20T00:06:06.801Z",
"stored":"2024-11-20T00:06:06.802+00:00",
"authority":{"mbox":"mailto:admin@my.xapi.net"}
}],
"more":null}"#;
let sr: StatementResult = serde_json::from_str(SR).unwrap();
assert_eq!(sr.statements().len(), 1);
}
}