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