xapi_rs/data/
statement_result.rs1use crate::data::{DataError, Statement, StatementId, validate_irl};
4use core::fmt;
5use iri_string::types::{IriStr, IriString};
6use serde::{Deserialize, Serialize};
7use serde_with::skip_serializing_none;
8use tracing::warn;
9
10#[skip_serializing_none]
17#[derive(Debug, Default, Deserialize, Serialize)]
18pub struct StatementResult {
19 statements: Vec<Statement>,
20 more: Option<IriString>,
21}
22
23#[skip_serializing_none]
24#[derive(Debug, Serialize)]
25pub(crate) struct StatementResultId {
26 statements: Vec<StatementId>,
27 more: Option<IriString>,
28}
29
30impl From<StatementResult> for StatementResultId {
31 fn from(value: StatementResult) -> Self {
32 StatementResultId {
33 statements: value
34 .statements
35 .into_iter()
36 .map(StatementId::from)
37 .collect(),
38 more: value.more,
39 }
40 }
41}
42
43impl StatementResult {
44 pub fn from(statements: Vec<Statement>) -> Self {
46 StatementResult {
47 statements,
48 more: None,
49 }
50 }
51
52 pub fn statements(&self) -> &Vec<Statement> {
54 self.statements.as_ref()
55 }
56
57 pub fn is_empty(&self) -> bool {
59 self.statements.is_empty()
60 }
61
62 pub fn more(&self) -> Option<&IriStr> {
64 self.more.as_deref()
65 }
66
67 pub fn set_more(&mut self, val: &str) -> Result<(), DataError> {
72 let s = val.trim();
73 if s.is_empty() {
74 warn!("Input value is empty. Unset URL");
75 self.more = None;
76 } else {
77 let iri = IriStr::new(s)?;
78 validate_irl(iri)?;
79 self.more = Some(iri.to_owned());
80 }
81 Ok(())
82 }
83}
84
85impl fmt::Display for StatementResult {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 let statements = self
88 .statements
89 .iter()
90 .map(|x| x.to_string())
91 .collect::<Vec<_>>()
92 .join(", ");
93 if self.more.is_some() {
94 write!(
95 f,
96 "StatementResult{{[ {} ], '{}'}}",
97 statements,
98 self.more.as_ref().unwrap()
99 )
100 } else {
101 write!(f, "StatementResult{{[ {statements} ]}}")
102 }
103 }
104}
105
106impl StatementResultId {
107 pub(crate) fn from(statements: Vec<StatementId>) -> Self {
108 StatementResultId {
109 statements,
110 more: None,
111 }
112 }
113
114 pub(crate) fn set_more(&mut self, val: &str) -> Result<(), DataError> {
115 let s = val.trim();
116 let iri = IriStr::new(s)?;
117 self.more = Some(iri.to_owned());
118 Ok(())
119 }
120
121 pub(crate) fn is_empty(&self) -> bool {
122 self.statements.is_empty()
123 }
124
125 pub(crate) fn statements(&self) -> &Vec<StatementId> {
126 self.statements.as_ref()
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_deserialization() {
136 const SR: &str = r#"{
137"statements":[{
138 "id":"01932d1e-a584-79d2-b83a-6b380546b21c",
139 "actor":{"mbox":"mailto:agent99@adlnet.gov"},
140 "verb":{"id":"http://adlnet.gov/expapi/verbs/attended"},
141 "object":{
142 "objectType":"SubStatement",
143 "actor":{"objectType":"Group","member":[],"mbox":"mailto:groupb@adlnet.gov"},
144 "verb":{"id":"http://adlnet.gov/expapi/verbs/attended"},
145 "object":{"id":"http://www.example.com/unicode/36c47486-83c8-4b4f-872c-67af87e9ad10"},
146 "timestamp":"2024-11-20T00:06:06.838Z"
147 },
148 "timestamp":"2024-11-20T00:06:06.801Z",
149 "stored":"2024-11-20T00:06:06.802+00:00",
150 "authority":{"mbox":"mailto:admin@my.xapi.net"}
151}],
152"more":null}"#;
153
154 let sr: StatementResult = serde_json::from_str(SR).unwrap();
155 assert_eq!(sr.statements().len(), 1);
156 }
157}