1#[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, Language};
20use jacquard_common::types::uri::{RecordUri, UriError};
21use jacquard_common::types::value::Data;
22use jacquard_common::xrpc::XrpcResp;
23use jacquard_derive::{IntoStatic, lexicon, open_union};
24use jacquard_lexicon::lexicon::LexiconDoc;
25use jacquard_lexicon::schema::LexiconSchema;
26
27use crate::app_bsky::embed::external::ExternalRecord;
28use crate::app_bsky::embed::gallery::Gallery;
29use crate::app_bsky::embed::images::Images;
30use crate::app_bsky::embed::record::Record;
31use crate::app_bsky::embed::record_with_media::RecordWithMedia;
32use crate::app_bsky::embed::video::Video;
33use crate::app_bsky::feed::post;
34use crate::app_bsky::richtext::facet::Facet;
35use crate::com_atproto::label::SelfLabels;
36use crate::com_atproto::repo::strong_ref::StrongRef;
37#[allow(unused_imports)]
38use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
39use serde::{Deserialize, Serialize};
40#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
43#[serde(
44 rename_all = "camelCase",
45 bound(deserialize = "S: Deserialize<'de> + BosStr")
46)]
47pub struct Entity<S: BosStr = DefaultStr> {
48 pub index: post::TextSlice<S>,
49 pub r#type: S,
51 pub value: S,
52 #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
53 pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
54}
55
56#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
59#[serde(
60 rename_all = "camelCase",
61 rename = "app.bsky.feed.post",
62 tag = "$type",
63 bound(deserialize = "S: Deserialize<'de> + BosStr")
64)]
65pub struct Post<S: BosStr = DefaultStr> {
66 pub created_at: Datetime,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub embed: Option<PostEmbed<S>>,
70 #[serde(skip_serializing_if = "Option::is_none")]
72 pub entities: Option<Vec<post::Entity<S>>>,
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub facets: Option<Vec<Facet<S>>>,
76 #[serde(skip_serializing_if = "Option::is_none")]
78 pub labels: Option<SelfLabels<S>>,
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub langs: Option<Vec<Language>>,
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub reply: Option<post::ReplyRef<S>>,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub tags: Option<Vec<S>>,
87 pub text: S,
89 #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
90 pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
91}
92
93#[open_union]
94#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
95#[serde(tag = "$type", bound(deserialize = "S: Deserialize<'de> + BosStr"))]
96pub enum PostEmbed<S: BosStr = DefaultStr> {
97 #[serde(rename = "app.bsky.embed.images")]
98 Images(Box<Images<S>>),
99 #[serde(rename = "app.bsky.embed.video")]
100 Video(Box<Video<S>>),
101 #[serde(rename = "app.bsky.embed.gallery")]
102 Gallery(Box<Gallery<S>>),
103 #[serde(rename = "app.bsky.embed.external")]
104 External(Box<ExternalRecord<S>>),
105 #[serde(rename = "app.bsky.embed.record")]
106 Record(Box<Record<S>>),
107 #[serde(rename = "app.bsky.embed.recordWithMedia")]
108 RecordWithMedia(Box<RecordWithMedia<S>>),
109}
110
111#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
114#[serde(rename_all = "camelCase")]
115pub struct PostGetRecordOutput<S: BosStr = DefaultStr> {
116 #[serde(skip_serializing_if = "Option::is_none")]
117 pub cid: Option<Cid<S>>,
118 pub uri: AtUri<S>,
119 pub value: Post<S>,
120}
121
122#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
123#[serde(
124 rename_all = "camelCase",
125 bound(deserialize = "S: Deserialize<'de> + BosStr")
126)]
127pub struct ReplyRef<S: BosStr = DefaultStr> {
128 pub parent: StrongRef<S>,
129 pub root: StrongRef<S>,
130 #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
131 pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
132}
133
134#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
137#[serde(
138 rename_all = "camelCase",
139 bound(deserialize = "S: Deserialize<'de> + BosStr")
140)]
141pub struct TextSlice<S: BosStr = DefaultStr> {
142 pub end: i64,
143 pub start: i64,
144 #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
145 pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
146}
147
148impl<S: BosStr> Post<S> {
149 pub fn uri(uri: S) -> Result<RecordUri<S, PostRecord>, UriError> {
150 RecordUri::try_from_uri(AtUri::new(uri)?)
151 }
152}
153
154impl<S: BosStr> LexiconSchema for Entity<S> {
155 fn nsid() -> &'static str {
156 "app.bsky.feed.post"
157 }
158 fn def_name() -> &'static str {
159 "entity"
160 }
161 fn lexicon_doc() -> LexiconDoc<'static> {
162 lexicon_doc_app_bsky_feed_post()
163 }
164 fn validate(&self) -> Result<(), ConstraintError> {
165 Ok(())
166 }
167}
168
169#[derive(Debug, Serialize, Deserialize)]
172pub struct PostRecord;
173impl XrpcResp for PostRecord {
174 const NSID: &'static str = "app.bsky.feed.post";
175 const ENCODING: &'static str = "application/json";
176 type Output<S: BosStr> = PostGetRecordOutput<S>;
177 type Err = RecordError;
178}
179
180impl<S: BosStr> From<PostGetRecordOutput<S>> for Post<S> {
181 fn from(output: PostGetRecordOutput<S>) -> Self {
182 output.value
183 }
184}
185
186impl<S: BosStr> Collection for Post<S> {
187 const NSID: &'static str = "app.bsky.feed.post";
188 type Record = PostRecord;
189}
190
191impl Collection for PostRecord {
192 const NSID: &'static str = "app.bsky.feed.post";
193 type Record = PostRecord;
194}
195
196impl<S: BosStr> LexiconSchema for Post<S> {
197 fn nsid() -> &'static str {
198 "app.bsky.feed.post"
199 }
200 fn def_name() -> &'static str {
201 "main"
202 }
203 fn lexicon_doc() -> LexiconDoc<'static> {
204 lexicon_doc_app_bsky_feed_post()
205 }
206 fn validate(&self) -> Result<(), ConstraintError> {
207 if let Some(ref value) = self.langs {
208 #[allow(unused_comparisons)]
209 if value.len() > 3usize {
210 return Err(ConstraintError::MaxLength {
211 path: ValidationPath::from_field("langs"),
212 max: 3usize,
213 actual: value.len(),
214 });
215 }
216 }
217 if let Some(ref value) = self.tags {
218 #[allow(unused_comparisons)]
219 if value.len() > 8usize {
220 return Err(ConstraintError::MaxLength {
221 path: ValidationPath::from_field("tags"),
222 max: 8usize,
223 actual: value.len(),
224 });
225 }
226 }
227 {
228 let value = &self.text;
229 #[allow(unused_comparisons)]
230 if <str>::len(value.as_ref()) > 3000usize {
231 return Err(ConstraintError::MaxLength {
232 path: ValidationPath::from_field("text"),
233 max: 3000usize,
234 actual: <str>::len(value.as_ref()),
235 });
236 }
237 }
238 {
239 let value = &self.text;
240 {
241 let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count();
242 if count > 300usize {
243 return Err(ConstraintError::MaxGraphemes {
244 path: ValidationPath::from_field("text"),
245 max: 300usize,
246 actual: count,
247 });
248 }
249 }
250 }
251 Ok(())
252 }
253}
254
255impl<S: BosStr> LexiconSchema for ReplyRef<S> {
256 fn nsid() -> &'static str {
257 "app.bsky.feed.post"
258 }
259 fn def_name() -> &'static str {
260 "replyRef"
261 }
262 fn lexicon_doc() -> LexiconDoc<'static> {
263 lexicon_doc_app_bsky_feed_post()
264 }
265 fn validate(&self) -> Result<(), ConstraintError> {
266 Ok(())
267 }
268}
269
270impl<S: BosStr> LexiconSchema for TextSlice<S> {
271 fn nsid() -> &'static str {
272 "app.bsky.feed.post"
273 }
274 fn def_name() -> &'static str {
275 "textSlice"
276 }
277 fn lexicon_doc() -> LexiconDoc<'static> {
278 lexicon_doc_app_bsky_feed_post()
279 }
280 fn validate(&self) -> Result<(), ConstraintError> {
281 {
282 let value = &self.end;
283 if *value < 0i64 {
284 return Err(ConstraintError::Minimum {
285 path: ValidationPath::from_field("end"),
286 min: 0i64,
287 actual: *value,
288 });
289 }
290 }
291 {
292 let value = &self.start;
293 if *value < 0i64 {
294 return Err(ConstraintError::Minimum {
295 path: ValidationPath::from_field("start"),
296 min: 0i64,
297 actual: *value,
298 });
299 }
300 }
301 Ok(())
302 }
303}
304
305pub mod entity_state {
306
307 pub use crate::builder_types::{IsSet, IsUnset, Set, Unset};
308 #[allow(unused)]
309 use ::core::marker::PhantomData;
310 mod sealed {
311 pub trait Sealed {}
312 }
313 pub trait State: sealed::Sealed {
315 type Index;
316 type Type;
317 type Value;
318 }
319 pub struct Empty(());
321 impl sealed::Sealed for Empty {}
322 impl State for Empty {
323 type Index = Unset;
324 type Type = Unset;
325 type Value = Unset;
326 }
327 pub struct SetIndex<St: State = Empty>(PhantomData<fn() -> St>);
329 impl<St: State> sealed::Sealed for SetIndex<St> {}
330 impl<St: State> State for SetIndex<St> {
331 type Index = Set<members::index>;
332 type Type = St::Type;
333 type Value = St::Value;
334 }
335 pub struct SetType<St: State = Empty>(PhantomData<fn() -> St>);
337 impl<St: State> sealed::Sealed for SetType<St> {}
338 impl<St: State> State for SetType<St> {
339 type Index = St::Index;
340 type Type = Set<members::r#type>;
341 type Value = St::Value;
342 }
343 pub struct SetValue<St: State = Empty>(PhantomData<fn() -> St>);
345 impl<St: State> sealed::Sealed for SetValue<St> {}
346 impl<St: State> State for SetValue<St> {
347 type Index = St::Index;
348 type Type = St::Type;
349 type Value = Set<members::value>;
350 }
351 #[allow(non_camel_case_types)]
353 pub mod members {
354 pub struct index(());
356 pub struct r#type(());
358 pub struct value(());
360 }
361}
362
363pub struct EntityBuilder<St: entity_state::State, S: BosStr = DefaultStr> {
365 _state: PhantomData<fn() -> St>,
366 _fields: (Option<post::TextSlice<S>>, Option<S>, Option<S>),
367 _type: PhantomData<fn() -> S>,
368}
369
370impl Entity<DefaultStr> {
371 pub fn new() -> EntityBuilder<entity_state::Empty, DefaultStr> {
373 EntityBuilder::new()
374 }
375}
376
377impl<S: BosStr> Entity<S> {
378 pub fn builder() -> EntityBuilder<entity_state::Empty, S> {
380 EntityBuilder::builder()
381 }
382}
383
384impl EntityBuilder<entity_state::Empty, DefaultStr> {
385 pub fn new() -> Self {
387 EntityBuilder {
388 _state: PhantomData,
389 _fields: (None, None, None),
390 _type: PhantomData,
391 }
392 }
393}
394
395impl<S: BosStr> EntityBuilder<entity_state::Empty, S> {
396 pub fn builder() -> Self {
398 EntityBuilder {
399 _state: PhantomData,
400 _fields: (None, None, None),
401 _type: PhantomData,
402 }
403 }
404}
405
406impl<St, S: BosStr> EntityBuilder<St, S>
407where
408 St: entity_state::State,
409 St::Index: entity_state::IsUnset,
410{
411 pub fn index(
413 mut self,
414 value: impl Into<post::TextSlice<S>>,
415 ) -> EntityBuilder<entity_state::SetIndex<St>, S> {
416 self._fields.0 = Option::Some(value.into());
417 EntityBuilder {
418 _state: PhantomData,
419 _fields: self._fields,
420 _type: PhantomData,
421 }
422 }
423}
424
425impl<St, S: BosStr> EntityBuilder<St, S>
426where
427 St: entity_state::State,
428 St::Type: entity_state::IsUnset,
429{
430 pub fn r#type(mut self, value: impl Into<S>) -> EntityBuilder<entity_state::SetType<St>, S> {
432 self._fields.1 = Option::Some(value.into());
433 EntityBuilder {
434 _state: PhantomData,
435 _fields: self._fields,
436 _type: PhantomData,
437 }
438 }
439}
440
441impl<St, S: BosStr> EntityBuilder<St, S>
442where
443 St: entity_state::State,
444 St::Value: entity_state::IsUnset,
445{
446 pub fn value(mut self, value: impl Into<S>) -> EntityBuilder<entity_state::SetValue<St>, S> {
448 self._fields.2 = Option::Some(value.into());
449 EntityBuilder {
450 _state: PhantomData,
451 _fields: self._fields,
452 _type: PhantomData,
453 }
454 }
455}
456
457impl<St, S: BosStr> EntityBuilder<St, S>
458where
459 St: entity_state::State,
460 St::Index: entity_state::IsSet,
461 St::Type: entity_state::IsSet,
462 St::Value: entity_state::IsSet,
463{
464 pub fn build(self) -> Entity<S> {
466 Entity {
467 index: self._fields.0.unwrap(),
468 r#type: self._fields.1.unwrap(),
469 value: self._fields.2.unwrap(),
470 extra_data: Default::default(),
471 }
472 }
473 pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> Entity<S> {
475 Entity {
476 index: self._fields.0.unwrap(),
477 r#type: self._fields.1.unwrap(),
478 value: self._fields.2.unwrap(),
479 extra_data: Some(extra_data),
480 }
481 }
482}
483
484fn lexicon_doc_app_bsky_feed_post() -> LexiconDoc<'static> {
485 use alloc::collections::BTreeMap;
486 #[allow(unused_imports)]
487 use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
488 use jacquard_lexicon::lexicon::*;
489 LexiconDoc {
490 lexicon: Lexicon::Lexicon1,
491 id: CowStr::new_static("app.bsky.feed.post"),
492 defs: {
493 let mut map = BTreeMap::new();
494 map.insert(
495 SmolStr::new_static("entity"),
496 LexUserType::Object(LexObject {
497 description: Some(CowStr::new_static("Deprecated: use facets instead.")),
498 required: Some(vec![
499 SmolStr::new_static("index"),
500 SmolStr::new_static("type"),
501 SmolStr::new_static("value"),
502 ]),
503 properties: {
504 #[allow(unused_mut)]
505 let mut map = BTreeMap::new();
506 map.insert(
507 SmolStr::new_static("index"),
508 LexObjectProperty::Ref(LexRef {
509 r#ref: CowStr::new_static("#textSlice"),
510 ..Default::default()
511 }),
512 );
513 map.insert(
514 SmolStr::new_static("type"),
515 LexObjectProperty::String(LexString {
516 description: Some(CowStr::new_static(
517 "Expected values are 'mention' and 'link'.",
518 )),
519 ..Default::default()
520 }),
521 );
522 map.insert(
523 SmolStr::new_static("value"),
524 LexObjectProperty::String(LexString {
525 ..Default::default()
526 }),
527 );
528 map
529 },
530 ..Default::default()
531 }),
532 );
533 map.insert(
534 SmolStr::new_static("main"),
535 LexUserType::Record(LexRecord {
536 description: Some(
537 CowStr::new_static("Record containing a Bluesky post."),
538 ),
539 key: Some(CowStr::new_static("tid")),
540 record: LexRecordRecord::Object(LexObject {
541 required: Some(
542 vec![
543 SmolStr::new_static("text"),
544 SmolStr::new_static("createdAt")
545 ],
546 ),
547 properties: {
548 #[allow(unused_mut)]
549 let mut map = BTreeMap::new();
550 map.insert(
551 SmolStr::new_static("createdAt"),
552 LexObjectProperty::String(LexString {
553 description: Some(
554 CowStr::new_static(
555 "Client-declared timestamp when this post was originally created.",
556 ),
557 ),
558 format: Some(LexStringFormat::Datetime),
559 ..Default::default()
560 }),
561 );
562 map.insert(
563 SmolStr::new_static("embed"),
564 LexObjectProperty::Union(LexRefUnion {
565 refs: vec![
566 CowStr::new_static("app.bsky.embed.images"),
567 CowStr::new_static("app.bsky.embed.video"),
568 CowStr::new_static("app.bsky.embed.gallery"),
569 CowStr::new_static("app.bsky.embed.external"),
570 CowStr::new_static("app.bsky.embed.record"),
571 CowStr::new_static("app.bsky.embed.recordWithMedia")
572 ],
573 ..Default::default()
574 }),
575 );
576 map.insert(
577 SmolStr::new_static("entities"),
578 LexObjectProperty::Array(LexArray {
579 description: Some(
580 CowStr::new_static(
581 "DEPRECATED: replaced by app.bsky.richtext.facet.",
582 ),
583 ),
584 items: LexArrayItem::Ref(LexRef {
585 r#ref: CowStr::new_static("#entity"),
586 ..Default::default()
587 }),
588 ..Default::default()
589 }),
590 );
591 map.insert(
592 SmolStr::new_static("facets"),
593 LexObjectProperty::Array(LexArray {
594 description: Some(
595 CowStr::new_static(
596 "Annotations of text (mentions, URLs, hashtags, etc)",
597 ),
598 ),
599 items: LexArrayItem::Ref(LexRef {
600 r#ref: CowStr::new_static("app.bsky.richtext.facet"),
601 ..Default::default()
602 }),
603 ..Default::default()
604 }),
605 );
606 map.insert(
607 SmolStr::new_static("labels"),
608 LexObjectProperty::Union(LexRefUnion {
609 description: Some(
610 CowStr::new_static(
611 "Self-label values for this post. Effectively content warnings.",
612 ),
613 ),
614 refs: vec![
615 CowStr::new_static("com.atproto.label.defs#selfLabels")
616 ],
617 ..Default::default()
618 }),
619 );
620 map.insert(
621 SmolStr::new_static("langs"),
622 LexObjectProperty::Array(LexArray {
623 description: Some(
624 CowStr::new_static(
625 "Indicates human language of post primary text content.",
626 ),
627 ),
628 items: LexArrayItem::String(LexString {
629 format: Some(LexStringFormat::Language),
630 ..Default::default()
631 }),
632 max_length: Some(3usize),
633 ..Default::default()
634 }),
635 );
636 map.insert(
637 SmolStr::new_static("reply"),
638 LexObjectProperty::Ref(LexRef {
639 r#ref: CowStr::new_static("#replyRef"),
640 ..Default::default()
641 }),
642 );
643 map.insert(
644 SmolStr::new_static("tags"),
645 LexObjectProperty::Array(LexArray {
646 description: Some(
647 CowStr::new_static(
648 "Additional hashtags, in addition to any included in post text and facets.",
649 ),
650 ),
651 items: LexArrayItem::String(LexString {
652 max_length: Some(640usize),
653 max_graphemes: Some(64usize),
654 ..Default::default()
655 }),
656 max_length: Some(8usize),
657 ..Default::default()
658 }),
659 );
660 map.insert(
661 SmolStr::new_static("text"),
662 LexObjectProperty::String(LexString {
663 description: Some(
664 CowStr::new_static(
665 "The primary post content. May be an empty string, if there are embeds.",
666 ),
667 ),
668 max_length: Some(3000usize),
669 max_graphemes: Some(300usize),
670 ..Default::default()
671 }),
672 );
673 map
674 },
675 ..Default::default()
676 }),
677 ..Default::default()
678 }),
679 );
680 map.insert(
681 SmolStr::new_static("replyRef"),
682 LexUserType::Object(LexObject {
683 required: Some(vec![
684 SmolStr::new_static("root"),
685 SmolStr::new_static("parent"),
686 ]),
687 properties: {
688 #[allow(unused_mut)]
689 let mut map = BTreeMap::new();
690 map.insert(
691 SmolStr::new_static("parent"),
692 LexObjectProperty::Ref(LexRef {
693 r#ref: CowStr::new_static("com.atproto.repo.strongRef"),
694 ..Default::default()
695 }),
696 );
697 map.insert(
698 SmolStr::new_static("root"),
699 LexObjectProperty::Ref(LexRef {
700 r#ref: CowStr::new_static("com.atproto.repo.strongRef"),
701 ..Default::default()
702 }),
703 );
704 map
705 },
706 ..Default::default()
707 }),
708 );
709 map.insert(
710 SmolStr::new_static("textSlice"),
711 LexUserType::Object(LexObject {
712 description: Some(
713 CowStr::new_static(
714 "Deprecated. Use app.bsky.richtext instead -- A text segment. Start is inclusive, end is exclusive. Indices are for utf16-encoded strings.",
715 ),
716 ),
717 required: Some(
718 vec![SmolStr::new_static("start"), SmolStr::new_static("end")],
719 ),
720 properties: {
721 #[allow(unused_mut)]
722 let mut map = BTreeMap::new();
723 map.insert(
724 SmolStr::new_static("end"),
725 LexObjectProperty::Integer(LexInteger {
726 minimum: Some(0i64),
727 ..Default::default()
728 }),
729 );
730 map.insert(
731 SmolStr::new_static("start"),
732 LexObjectProperty::Integer(LexInteger {
733 minimum: Some(0i64),
734 ..Default::default()
735 }),
736 );
737 map
738 },
739 ..Default::default()
740 }),
741 );
742 map
743 },
744 ..Default::default()
745 }
746}
747
748pub mod post_state {
749
750 pub use crate::builder_types::{IsSet, IsUnset, Set, Unset};
751 #[allow(unused)]
752 use ::core::marker::PhantomData;
753 mod sealed {
754 pub trait Sealed {}
755 }
756 pub trait State: sealed::Sealed {
758 type CreatedAt;
759 type Text;
760 }
761 pub struct Empty(());
763 impl sealed::Sealed for Empty {}
764 impl State for Empty {
765 type CreatedAt = Unset;
766 type Text = Unset;
767 }
768 pub struct SetCreatedAt<St: State = Empty>(PhantomData<fn() -> St>);
770 impl<St: State> sealed::Sealed for SetCreatedAt<St> {}
771 impl<St: State> State for SetCreatedAt<St> {
772 type CreatedAt = Set<members::created_at>;
773 type Text = St::Text;
774 }
775 pub struct SetText<St: State = Empty>(PhantomData<fn() -> St>);
777 impl<St: State> sealed::Sealed for SetText<St> {}
778 impl<St: State> State for SetText<St> {
779 type CreatedAt = St::CreatedAt;
780 type Text = Set<members::text>;
781 }
782 #[allow(non_camel_case_types)]
784 pub mod members {
785 pub struct created_at(());
787 pub struct text(());
789 }
790}
791
792pub struct PostBuilder<St: post_state::State, S: BosStr = DefaultStr> {
794 _state: PhantomData<fn() -> St>,
795 _fields: (
796 Option<Datetime>,
797 Option<PostEmbed<S>>,
798 Option<Vec<post::Entity<S>>>,
799 Option<Vec<Facet<S>>>,
800 Option<SelfLabels<S>>,
801 Option<Vec<Language>>,
802 Option<post::ReplyRef<S>>,
803 Option<Vec<S>>,
804 Option<S>,
805 ),
806 _type: PhantomData<fn() -> S>,
807}
808
809impl Post<DefaultStr> {
810 pub fn new() -> PostBuilder<post_state::Empty, DefaultStr> {
812 PostBuilder::new()
813 }
814}
815
816impl<S: BosStr> Post<S> {
817 pub fn builder() -> PostBuilder<post_state::Empty, S> {
819 PostBuilder::builder()
820 }
821}
822
823impl PostBuilder<post_state::Empty, DefaultStr> {
824 pub fn new() -> Self {
826 PostBuilder {
827 _state: PhantomData,
828 _fields: (None, None, None, None, None, None, None, None, None),
829 _type: PhantomData,
830 }
831 }
832}
833
834impl<S: BosStr> PostBuilder<post_state::Empty, S> {
835 pub fn builder() -> Self {
837 PostBuilder {
838 _state: PhantomData,
839 _fields: (None, None, None, None, None, None, None, None, None),
840 _type: PhantomData,
841 }
842 }
843}
844
845impl<St, S: BosStr> PostBuilder<St, S>
846where
847 St: post_state::State,
848 St::CreatedAt: post_state::IsUnset,
849{
850 pub fn created_at(
852 mut self,
853 value: impl Into<Datetime>,
854 ) -> PostBuilder<post_state::SetCreatedAt<St>, S> {
855 self._fields.0 = Option::Some(value.into());
856 PostBuilder {
857 _state: PhantomData,
858 _fields: self._fields,
859 _type: PhantomData,
860 }
861 }
862}
863
864impl<St: post_state::State, S: BosStr> PostBuilder<St, S> {
865 pub fn embed(mut self, value: impl Into<Option<PostEmbed<S>>>) -> Self {
867 self._fields.1 = value.into();
868 self
869 }
870 pub fn maybe_embed(mut self, value: Option<PostEmbed<S>>) -> Self {
872 self._fields.1 = value;
873 self
874 }
875}
876
877impl<St: post_state::State, S: BosStr> PostBuilder<St, S> {
878 pub fn entities(mut self, value: impl Into<Option<Vec<post::Entity<S>>>>) -> Self {
880 self._fields.2 = value.into();
881 self
882 }
883 pub fn maybe_entities(mut self, value: Option<Vec<post::Entity<S>>>) -> Self {
885 self._fields.2 = value;
886 self
887 }
888}
889
890impl<St: post_state::State, S: BosStr> PostBuilder<St, S> {
891 pub fn facets(mut self, value: impl Into<Option<Vec<Facet<S>>>>) -> Self {
893 self._fields.3 = value.into();
894 self
895 }
896 pub fn maybe_facets(mut self, value: Option<Vec<Facet<S>>>) -> Self {
898 self._fields.3 = value;
899 self
900 }
901}
902
903impl<St: post_state::State, S: BosStr> PostBuilder<St, S> {
904 pub fn labels(mut self, value: impl Into<Option<SelfLabels<S>>>) -> Self {
906 self._fields.4 = value.into();
907 self
908 }
909 pub fn maybe_labels(mut self, value: Option<SelfLabels<S>>) -> Self {
911 self._fields.4 = value;
912 self
913 }
914}
915
916impl<St: post_state::State, S: BosStr> PostBuilder<St, S> {
917 pub fn langs(mut self, value: impl Into<Option<Vec<Language>>>) -> Self {
919 self._fields.5 = value.into();
920 self
921 }
922 pub fn maybe_langs(mut self, value: Option<Vec<Language>>) -> Self {
924 self._fields.5 = value;
925 self
926 }
927}
928
929impl<St: post_state::State, S: BosStr> PostBuilder<St, S> {
930 pub fn reply(mut self, value: impl Into<Option<post::ReplyRef<S>>>) -> Self {
932 self._fields.6 = value.into();
933 self
934 }
935 pub fn maybe_reply(mut self, value: Option<post::ReplyRef<S>>) -> Self {
937 self._fields.6 = value;
938 self
939 }
940}
941
942impl<St: post_state::State, S: BosStr> PostBuilder<St, S> {
943 pub fn tags(mut self, value: impl Into<Option<Vec<S>>>) -> Self {
945 self._fields.7 = value.into();
946 self
947 }
948 pub fn maybe_tags(mut self, value: Option<Vec<S>>) -> Self {
950 self._fields.7 = value;
951 self
952 }
953}
954
955impl<St, S: BosStr> PostBuilder<St, S>
956where
957 St: post_state::State,
958 St::Text: post_state::IsUnset,
959{
960 pub fn text(mut self, value: impl Into<S>) -> PostBuilder<post_state::SetText<St>, S> {
962 self._fields.8 = Option::Some(value.into());
963 PostBuilder {
964 _state: PhantomData,
965 _fields: self._fields,
966 _type: PhantomData,
967 }
968 }
969}
970
971impl<St, S: BosStr> PostBuilder<St, S>
972where
973 St: post_state::State,
974 St::CreatedAt: post_state::IsSet,
975 St::Text: post_state::IsSet,
976{
977 pub fn build(self) -> Post<S> {
979 Post {
980 created_at: self._fields.0.unwrap(),
981 embed: self._fields.1,
982 entities: self._fields.2,
983 facets: self._fields.3,
984 labels: self._fields.4,
985 langs: self._fields.5,
986 reply: self._fields.6,
987 tags: self._fields.7,
988 text: self._fields.8.unwrap(),
989 extra_data: Default::default(),
990 }
991 }
992 pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> Post<S> {
994 Post {
995 created_at: self._fields.0.unwrap(),
996 embed: self._fields.1,
997 entities: self._fields.2,
998 facets: self._fields.3,
999 labels: self._fields.4,
1000 langs: self._fields.5,
1001 reply: self._fields.6,
1002 tags: self._fields.7,
1003 text: self._fields.8.unwrap(),
1004 extra_data: Some(extra_data),
1005 }
1006 }
1007}
1008
1009pub mod reply_ref_state {
1010
1011 pub use crate::builder_types::{IsSet, IsUnset, Set, Unset};
1012 #[allow(unused)]
1013 use ::core::marker::PhantomData;
1014 mod sealed {
1015 pub trait Sealed {}
1016 }
1017 pub trait State: sealed::Sealed {
1019 type Parent;
1020 type Root;
1021 }
1022 pub struct Empty(());
1024 impl sealed::Sealed for Empty {}
1025 impl State for Empty {
1026 type Parent = Unset;
1027 type Root = Unset;
1028 }
1029 pub struct SetParent<St: State = Empty>(PhantomData<fn() -> St>);
1031 impl<St: State> sealed::Sealed for SetParent<St> {}
1032 impl<St: State> State for SetParent<St> {
1033 type Parent = Set<members::parent>;
1034 type Root = St::Root;
1035 }
1036 pub struct SetRoot<St: State = Empty>(PhantomData<fn() -> St>);
1038 impl<St: State> sealed::Sealed for SetRoot<St> {}
1039 impl<St: State> State for SetRoot<St> {
1040 type Parent = St::Parent;
1041 type Root = Set<members::root>;
1042 }
1043 #[allow(non_camel_case_types)]
1045 pub mod members {
1046 pub struct parent(());
1048 pub struct root(());
1050 }
1051}
1052
1053pub struct ReplyRefBuilder<St: reply_ref_state::State, S: BosStr = DefaultStr> {
1055 _state: PhantomData<fn() -> St>,
1056 _fields: (Option<StrongRef<S>>, Option<StrongRef<S>>),
1057 _type: PhantomData<fn() -> S>,
1058}
1059
1060impl ReplyRef<DefaultStr> {
1061 pub fn new() -> ReplyRefBuilder<reply_ref_state::Empty, DefaultStr> {
1063 ReplyRefBuilder::new()
1064 }
1065}
1066
1067impl<S: BosStr> ReplyRef<S> {
1068 pub fn builder() -> ReplyRefBuilder<reply_ref_state::Empty, S> {
1070 ReplyRefBuilder::builder()
1071 }
1072}
1073
1074impl ReplyRefBuilder<reply_ref_state::Empty, DefaultStr> {
1075 pub fn new() -> Self {
1077 ReplyRefBuilder {
1078 _state: PhantomData,
1079 _fields: (None, None),
1080 _type: PhantomData,
1081 }
1082 }
1083}
1084
1085impl<S: BosStr> ReplyRefBuilder<reply_ref_state::Empty, S> {
1086 pub fn builder() -> Self {
1088 ReplyRefBuilder {
1089 _state: PhantomData,
1090 _fields: (None, None),
1091 _type: PhantomData,
1092 }
1093 }
1094}
1095
1096impl<St, S: BosStr> ReplyRefBuilder<St, S>
1097where
1098 St: reply_ref_state::State,
1099 St::Parent: reply_ref_state::IsUnset,
1100{
1101 pub fn parent(
1103 mut self,
1104 value: impl Into<StrongRef<S>>,
1105 ) -> ReplyRefBuilder<reply_ref_state::SetParent<St>, S> {
1106 self._fields.0 = Option::Some(value.into());
1107 ReplyRefBuilder {
1108 _state: PhantomData,
1109 _fields: self._fields,
1110 _type: PhantomData,
1111 }
1112 }
1113}
1114
1115impl<St, S: BosStr> ReplyRefBuilder<St, S>
1116where
1117 St: reply_ref_state::State,
1118 St::Root: reply_ref_state::IsUnset,
1119{
1120 pub fn root(
1122 mut self,
1123 value: impl Into<StrongRef<S>>,
1124 ) -> ReplyRefBuilder<reply_ref_state::SetRoot<St>, S> {
1125 self._fields.1 = Option::Some(value.into());
1126 ReplyRefBuilder {
1127 _state: PhantomData,
1128 _fields: self._fields,
1129 _type: PhantomData,
1130 }
1131 }
1132}
1133
1134impl<St, S: BosStr> ReplyRefBuilder<St, S>
1135where
1136 St: reply_ref_state::State,
1137 St::Parent: reply_ref_state::IsSet,
1138 St::Root: reply_ref_state::IsSet,
1139{
1140 pub fn build(self) -> ReplyRef<S> {
1142 ReplyRef {
1143 parent: self._fields.0.unwrap(),
1144 root: self._fields.1.unwrap(),
1145 extra_data: Default::default(),
1146 }
1147 }
1148 pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> ReplyRef<S> {
1150 ReplyRef {
1151 parent: self._fields.0.unwrap(),
1152 root: self._fields.1.unwrap(),
1153 extra_data: Some(extra_data),
1154 }
1155 }
1156}
1157
1158pub mod text_slice_state {
1159
1160 pub use crate::builder_types::{IsSet, IsUnset, Set, Unset};
1161 #[allow(unused)]
1162 use ::core::marker::PhantomData;
1163 mod sealed {
1164 pub trait Sealed {}
1165 }
1166 pub trait State: sealed::Sealed {
1168 type End;
1169 type Start;
1170 }
1171 pub struct Empty(());
1173 impl sealed::Sealed for Empty {}
1174 impl State for Empty {
1175 type End = Unset;
1176 type Start = Unset;
1177 }
1178 pub struct SetEnd<St: State = Empty>(PhantomData<fn() -> St>);
1180 impl<St: State> sealed::Sealed for SetEnd<St> {}
1181 impl<St: State> State for SetEnd<St> {
1182 type End = Set<members::end>;
1183 type Start = St::Start;
1184 }
1185 pub struct SetStart<St: State = Empty>(PhantomData<fn() -> St>);
1187 impl<St: State> sealed::Sealed for SetStart<St> {}
1188 impl<St: State> State for SetStart<St> {
1189 type End = St::End;
1190 type Start = Set<members::start>;
1191 }
1192 #[allow(non_camel_case_types)]
1194 pub mod members {
1195 pub struct end(());
1197 pub struct start(());
1199 }
1200}
1201
1202pub struct TextSliceBuilder<St: text_slice_state::State, S: BosStr = DefaultStr> {
1204 _state: PhantomData<fn() -> St>,
1205 _fields: (Option<i64>, Option<i64>),
1206 _type: PhantomData<fn() -> S>,
1207}
1208
1209impl TextSlice<DefaultStr> {
1210 pub fn new() -> TextSliceBuilder<text_slice_state::Empty, DefaultStr> {
1212 TextSliceBuilder::new()
1213 }
1214}
1215
1216impl<S: BosStr> TextSlice<S> {
1217 pub fn builder() -> TextSliceBuilder<text_slice_state::Empty, S> {
1219 TextSliceBuilder::builder()
1220 }
1221}
1222
1223impl TextSliceBuilder<text_slice_state::Empty, DefaultStr> {
1224 pub fn new() -> Self {
1226 TextSliceBuilder {
1227 _state: PhantomData,
1228 _fields: (None, None),
1229 _type: PhantomData,
1230 }
1231 }
1232}
1233
1234impl<S: BosStr> TextSliceBuilder<text_slice_state::Empty, S> {
1235 pub fn builder() -> Self {
1237 TextSliceBuilder {
1238 _state: PhantomData,
1239 _fields: (None, None),
1240 _type: PhantomData,
1241 }
1242 }
1243}
1244
1245impl<St, S: BosStr> TextSliceBuilder<St, S>
1246where
1247 St: text_slice_state::State,
1248 St::End: text_slice_state::IsUnset,
1249{
1250 pub fn end(
1252 mut self,
1253 value: impl Into<i64>,
1254 ) -> TextSliceBuilder<text_slice_state::SetEnd<St>, S> {
1255 self._fields.0 = Option::Some(value.into());
1256 TextSliceBuilder {
1257 _state: PhantomData,
1258 _fields: self._fields,
1259 _type: PhantomData,
1260 }
1261 }
1262}
1263
1264impl<St, S: BosStr> TextSliceBuilder<St, S>
1265where
1266 St: text_slice_state::State,
1267 St::Start: text_slice_state::IsUnset,
1268{
1269 pub fn start(
1271 mut self,
1272 value: impl Into<i64>,
1273 ) -> TextSliceBuilder<text_slice_state::SetStart<St>, S> {
1274 self._fields.1 = Option::Some(value.into());
1275 TextSliceBuilder {
1276 _state: PhantomData,
1277 _fields: self._fields,
1278 _type: PhantomData,
1279 }
1280 }
1281}
1282
1283impl<St, S: BosStr> TextSliceBuilder<St, S>
1284where
1285 St: text_slice_state::State,
1286 St::End: text_slice_state::IsSet,
1287 St::Start: text_slice_state::IsSet,
1288{
1289 pub fn build(self) -> TextSlice<S> {
1291 TextSlice {
1292 end: self._fields.0.unwrap(),
1293 start: self._fields.1.unwrap(),
1294 extra_data: Default::default(),
1295 }
1296 }
1297 pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> TextSlice<S> {
1299 TextSlice {
1300 end: self._fields.0.unwrap(),
1301 start: self._fields.1.unwrap(),
1302 extra_data: Some(extra_data),
1303 }
1304 }
1305}