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