jacquard_api/net_anisota/feed/
perception.rs1#[allow(unused_imports)]
9use alloc::collections::BTreeMap;
10
11#[allow(unused_imports)]
12use core::marker::PhantomData;
13use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr};
14
15#[allow(unused_imports)]
16use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation;
17use jacquard_common::deps::smol_str::SmolStr;
18use jacquard_common::types::collection::{Collection, RecordError};
19use jacquard_common::types::string::{AtUri, Cid, Datetime};
20use jacquard_common::types::uri::{RecordUri, UriError};
21use jacquard_common::types::value::Data;
22use jacquard_common::xrpc::XrpcResp;
23use jacquard_derive::{IntoStatic, lexicon};
24use jacquard_lexicon::lexicon::LexiconDoc;
25use jacquard_lexicon::schema::LexiconSchema;
26
27use crate::com_atproto::repo::strong_ref::StrongRef;
28#[allow(unused_imports)]
29use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
30use serde::{Deserialize, Serialize};
31#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
34#[serde(
35 rename_all = "camelCase",
36 rename = "net.anisota.feed.perception",
37 tag = "$type",
38 bound(deserialize = "S: Deserialize<'de> + BosStr")
39)]
40pub struct Perception<S: BosStr = DefaultStr> {
41 pub created_at: Datetime,
43 pub subject: StrongRef<S>,
45 pub text: S,
47 #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
48 pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
49}
50
51#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
54#[serde(rename_all = "camelCase")]
55pub struct PerceptionGetRecordOutput<S: BosStr = DefaultStr> {
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub cid: Option<Cid<S>>,
58 pub uri: AtUri<S>,
59 pub value: Perception<S>,
60}
61
62impl<S: BosStr> Perception<S> {
63 pub fn uri(uri: S) -> Result<RecordUri<S, PerceptionRecord>, UriError> {
64 RecordUri::try_from_uri(AtUri::new(uri)?)
65 }
66}
67
68#[derive(Debug, Serialize, Deserialize)]
71pub struct PerceptionRecord;
72impl XrpcResp for PerceptionRecord {
73 const NSID: &'static str = "net.anisota.feed.perception";
74 const ENCODING: &'static str = "application/json";
75 type Output<S: BosStr> = PerceptionGetRecordOutput<S>;
76 type Err = RecordError;
77}
78
79impl<S: BosStr> From<PerceptionGetRecordOutput<S>> for Perception<S> {
80 fn from(output: PerceptionGetRecordOutput<S>) -> Self {
81 output.value
82 }
83}
84
85impl<S: BosStr> Collection for Perception<S> {
86 const NSID: &'static str = "net.anisota.feed.perception";
87 type Record = PerceptionRecord;
88}
89
90impl Collection for PerceptionRecord {
91 const NSID: &'static str = "net.anisota.feed.perception";
92 type Record = PerceptionRecord;
93}
94
95impl<S: BosStr> LexiconSchema for Perception<S> {
96 fn nsid() -> &'static str {
97 "net.anisota.feed.perception"
98 }
99 fn def_name() -> &'static str {
100 "main"
101 }
102 fn lexicon_doc() -> LexiconDoc<'static> {
103 lexicon_doc_net_anisota_feed_perception()
104 }
105 fn validate(&self) -> Result<(), ConstraintError> {
106 {
107 let value = &self.text;
108 #[allow(unused_comparisons)]
109 if <str>::len(value.as_ref()) > 1200usize {
110 return Err(ConstraintError::MaxLength {
111 path: ValidationPath::from_field("text"),
112 max: 1200usize,
113 actual: <str>::len(value.as_ref()),
114 });
115 }
116 }
117 {
118 let value = &self.text;
119 {
120 let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count();
121 if count > 300usize {
122 return Err(ConstraintError::MaxGraphemes {
123 path: ValidationPath::from_field("text"),
124 max: 300usize,
125 actual: count,
126 });
127 }
128 }
129 }
130 Ok(())
131 }
132}
133
134pub mod perception_state {
135
136 pub use crate::builder_types::{IsSet, IsUnset, Set, Unset};
137 #[allow(unused)]
138 use ::core::marker::PhantomData;
139 mod sealed {
140 pub trait Sealed {}
141 }
142 pub trait State: sealed::Sealed {
144 type CreatedAt;
145 type Subject;
146 type Text;
147 }
148 pub struct Empty(());
150 impl sealed::Sealed for Empty {}
151 impl State for Empty {
152 type CreatedAt = Unset;
153 type Subject = Unset;
154 type Text = Unset;
155 }
156 pub struct SetCreatedAt<St: State = Empty>(PhantomData<fn() -> St>);
158 impl<St: State> sealed::Sealed for SetCreatedAt<St> {}
159 impl<St: State> State for SetCreatedAt<St> {
160 type CreatedAt = Set<members::created_at>;
161 type Subject = St::Subject;
162 type Text = St::Text;
163 }
164 pub struct SetSubject<St: State = Empty>(PhantomData<fn() -> St>);
166 impl<St: State> sealed::Sealed for SetSubject<St> {}
167 impl<St: State> State for SetSubject<St> {
168 type CreatedAt = St::CreatedAt;
169 type Subject = Set<members::subject>;
170 type Text = St::Text;
171 }
172 pub struct SetText<St: State = Empty>(PhantomData<fn() -> St>);
174 impl<St: State> sealed::Sealed for SetText<St> {}
175 impl<St: State> State for SetText<St> {
176 type CreatedAt = St::CreatedAt;
177 type Subject = St::Subject;
178 type Text = Set<members::text>;
179 }
180 #[allow(non_camel_case_types)]
182 pub mod members {
183 pub struct created_at(());
185 pub struct subject(());
187 pub struct text(());
189 }
190}
191
192pub struct PerceptionBuilder<St: perception_state::State, S: BosStr = DefaultStr> {
194 _state: PhantomData<fn() -> St>,
195 _fields: (Option<Datetime>, Option<StrongRef<S>>, Option<S>),
196 _type: PhantomData<fn() -> S>,
197}
198
199impl Perception<DefaultStr> {
200 pub fn new() -> PerceptionBuilder<perception_state::Empty, DefaultStr> {
202 PerceptionBuilder::new()
203 }
204}
205
206impl<S: BosStr> Perception<S> {
207 pub fn builder() -> PerceptionBuilder<perception_state::Empty, S> {
209 PerceptionBuilder::builder()
210 }
211}
212
213impl PerceptionBuilder<perception_state::Empty, DefaultStr> {
214 pub fn new() -> Self {
216 PerceptionBuilder {
217 _state: PhantomData,
218 _fields: (None, None, None),
219 _type: PhantomData,
220 }
221 }
222}
223
224impl<S: BosStr> PerceptionBuilder<perception_state::Empty, S> {
225 pub fn builder() -> Self {
227 PerceptionBuilder {
228 _state: PhantomData,
229 _fields: (None, None, None),
230 _type: PhantomData,
231 }
232 }
233}
234
235impl<St, S: BosStr> PerceptionBuilder<St, S>
236where
237 St: perception_state::State,
238 St::CreatedAt: perception_state::IsUnset,
239{
240 pub fn created_at(
242 mut self,
243 value: impl Into<Datetime>,
244 ) -> PerceptionBuilder<perception_state::SetCreatedAt<St>, S> {
245 self._fields.0 = Option::Some(value.into());
246 PerceptionBuilder {
247 _state: PhantomData,
248 _fields: self._fields,
249 _type: PhantomData,
250 }
251 }
252}
253
254impl<St, S: BosStr> PerceptionBuilder<St, S>
255where
256 St: perception_state::State,
257 St::Subject: perception_state::IsUnset,
258{
259 pub fn subject(
261 mut self,
262 value: impl Into<StrongRef<S>>,
263 ) -> PerceptionBuilder<perception_state::SetSubject<St>, S> {
264 self._fields.1 = Option::Some(value.into());
265 PerceptionBuilder {
266 _state: PhantomData,
267 _fields: self._fields,
268 _type: PhantomData,
269 }
270 }
271}
272
273impl<St, S: BosStr> PerceptionBuilder<St, S>
274where
275 St: perception_state::State,
276 St::Text: perception_state::IsUnset,
277{
278 pub fn text(
280 mut self,
281 value: impl Into<S>,
282 ) -> PerceptionBuilder<perception_state::SetText<St>, S> {
283 self._fields.2 = Option::Some(value.into());
284 PerceptionBuilder {
285 _state: PhantomData,
286 _fields: self._fields,
287 _type: PhantomData,
288 }
289 }
290}
291
292impl<St, S: BosStr> PerceptionBuilder<St, S>
293where
294 St: perception_state::State,
295 St::CreatedAt: perception_state::IsSet,
296 St::Subject: perception_state::IsSet,
297 St::Text: perception_state::IsSet,
298{
299 pub fn build(self) -> Perception<S> {
301 Perception {
302 created_at: self._fields.0.unwrap(),
303 subject: self._fields.1.unwrap(),
304 text: self._fields.2.unwrap(),
305 extra_data: Default::default(),
306 }
307 }
308 pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> Perception<S> {
310 Perception {
311 created_at: self._fields.0.unwrap(),
312 subject: self._fields.1.unwrap(),
313 text: self._fields.2.unwrap(),
314 extra_data: Some(extra_data),
315 }
316 }
317}
318
319fn lexicon_doc_net_anisota_feed_perception() -> LexiconDoc<'static> {
320 use alloc::collections::BTreeMap;
321 #[allow(unused_imports)]
322 use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
323 use jacquard_lexicon::lexicon::*;
324 LexiconDoc {
325 lexicon: Lexicon::Lexicon1,
326 id: CowStr::new_static("net.anisota.feed.perception"),
327 defs: {
328 let mut map = BTreeMap::new();
329 map.insert(
330 SmolStr::new_static("main"),
331 LexUserType::Record(LexRecord {
332 description: Some(
333 CowStr::new_static(
334 "One person's perception of an inkblot — their answer to 'what do you see?'. Points at the inkblot record via a strongRef 'subject'. A social response (not a lab creation), so it lives in the feed.* namespace. In the Social Inkblot Test, a viewer's own perception is written before everyone else's perceptions of the same blot are revealed (so the first impression is uncontaminated). Perceptions are aggregated through the Constellation backlink index on '.subject.uri'. Renamed from net.anisota.lab.inkblot.perception.",
335 ),
336 ),
337 key: Some(CowStr::new_static("tid")),
338 record: LexRecordRecord::Object(LexObject {
339 required: Some(
340 vec![
341 SmolStr::new_static("subject"), SmolStr::new_static("text"),
342 SmolStr::new_static("createdAt")
343 ],
344 ),
345 properties: {
346 #[allow(unused_mut)]
347 let mut map = BTreeMap::new();
348 map.insert(
349 SmolStr::new_static("createdAt"),
350 LexObjectProperty::String(LexString {
351 description: Some(
352 CowStr::new_static("When the perception was written"),
353 ),
354 format: Some(LexStringFormat::Datetime),
355 ..Default::default()
356 }),
357 );
358 map.insert(
359 SmolStr::new_static("subject"),
360 LexObjectProperty::Ref(LexRef {
361 r#ref: CowStr::new_static("com.atproto.repo.strongRef"),
362 ..Default::default()
363 }),
364 );
365 map.insert(
366 SmolStr::new_static("text"),
367 LexObjectProperty::String(LexString {
368 description: Some(
369 CowStr::new_static("What the viewer sees in the blot"),
370 ),
371 max_length: Some(1200usize),
372 max_graphemes: Some(300usize),
373 ..Default::default()
374 }),
375 );
376 map
377 },
378 ..Default::default()
379 }),
380 ..Default::default()
381 }),
382 );
383 map
384 },
385 ..Default::default()
386 }
387}