Skip to main content

jacquard_api/app_bsky/embed/
video.rs

1// @generated by jacquard-lexicon. DO NOT EDIT.
2//
3// Lexicon: app.bsky.embed.video
4//
5// This file was automatically generated from Lexicon schemas.
6// Any manual changes will be overwritten on the next regeneration.
7
8#[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::blob::BlobRef;
19use jacquard_common::types::string::{Cid, Language, UriValue};
20use jacquard_common::types::value::Data;
21use jacquard_derive::IntoStatic;
22use jacquard_lexicon::lexicon::LexiconDoc;
23use jacquard_lexicon::schema::LexiconSchema;
24
25#[allow(unused_imports)]
26use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
27use serde::{Serialize, Deserialize};
28use crate::app_bsky::embed::AspectRatio;
29use crate::app_bsky::embed::video;
30
31#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
32#[serde(rename_all = "camelCase", bound(deserialize = "S: Deserialize<'de> + BosStr"))]
33pub struct Caption<S: BosStr = DefaultStr> {
34    pub file: BlobRef<S>,
35    pub lang: Language,
36    #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
37    pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
38}
39
40
41#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
42#[serde(rename_all = "camelCase", bound(deserialize = "S: Deserialize<'de> + BosStr"))]
43pub struct Video<S: BosStr = DefaultStr> {
44    ///Alt text description of the video, for accessibility.
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub alt: Option<S>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub aspect_ratio: Option<AspectRatio<S>>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub captions: Option<Vec<video::Caption<S>>>,
51    ///A hint to the client about how to present the video.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub presentation: Option<VideoPresentation<S>>,
54    ///The mp4 video file. May be up to 100mb, formerly limited to 50mb.
55    pub video: BlobRef<S>,
56    #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
57    pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
58}
59
60/// A hint to the client about how to present the video.
61
62#[derive(Debug, Clone, PartialEq, Eq, Hash)]
63pub enum VideoPresentation<S: BosStr = DefaultStr> {
64    Default,
65    Gif,
66    Other(S),
67}
68
69impl<S: BosStr> VideoPresentation<S> {
70    pub fn as_str(&self) -> &str {
71        match self {
72            Self::Default => "default",
73            Self::Gif => "gif",
74            Self::Other(s) => s.as_ref(),
75        }
76    }
77    /// Construct from a string-like value, matching known values.
78    pub fn from_value(s: S) -> Self {
79        match s.as_ref() {
80            "default" => Self::Default,
81            "gif" => Self::Gif,
82            _ => Self::Other(s),
83        }
84    }
85}
86
87impl<S: BosStr> core::fmt::Display for VideoPresentation<S> {
88    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
89        write!(f, "{}", self.as_str())
90    }
91}
92
93impl<S: BosStr> AsRef<str> for VideoPresentation<S> {
94    fn as_ref(&self) -> &str {
95        self.as_str()
96    }
97}
98
99impl<S: BosStr> Serialize for VideoPresentation<S> {
100    fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
101    where
102        Ser: serde::Serializer,
103    {
104        serializer.serialize_str(self.as_str())
105    }
106}
107
108impl<'de, S: Deserialize<'de> + BosStr> Deserialize<'de> for VideoPresentation<S> {
109    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
110    where
111        D: serde::Deserializer<'de>,
112    {
113        let s = S::deserialize(deserializer)?;
114        Ok(Self::from_value(s))
115    }
116}
117
118impl<S: BosStr + Default> Default for VideoPresentation<S> {
119    fn default() -> Self {
120        Self::Other(Default::default())
121    }
122}
123
124impl<S: BosStr> jacquard_common::IntoStatic for VideoPresentation<S>
125where
126    S: BosStr + jacquard_common::IntoStatic,
127    S::Output: BosStr,
128{
129    type Output = VideoPresentation<S::Output>;
130    fn into_static(self) -> Self::Output {
131        match self {
132            VideoPresentation::Default => VideoPresentation::Default,
133            VideoPresentation::Gif => VideoPresentation::Gif,
134            VideoPresentation::Other(v) => VideoPresentation::Other(v.into_static()),
135        }
136    }
137}
138
139
140#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
141#[serde(rename_all = "camelCase", bound(deserialize = "S: Deserialize<'de> + BosStr"))]
142pub struct View<S: BosStr = DefaultStr> {
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub alt: Option<S>,
145    #[serde(skip_serializing_if = "Option::is_none")]
146    pub aspect_ratio: Option<AspectRatio<S>>,
147    pub cid: Cid<S>,
148    pub playlist: UriValue<S>,
149    ///A hint to the client about how to present the video.
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub presentation: Option<ViewPresentation<S>>,
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub thumbnail: Option<UriValue<S>>,
154    #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
155    pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
156}
157
158/// A hint to the client about how to present the video.
159
160#[derive(Debug, Clone, PartialEq, Eq, Hash)]
161pub enum ViewPresentation<S: BosStr = DefaultStr> {
162    Default,
163    Gif,
164    Other(S),
165}
166
167impl<S: BosStr> ViewPresentation<S> {
168    pub fn as_str(&self) -> &str {
169        match self {
170            Self::Default => "default",
171            Self::Gif => "gif",
172            Self::Other(s) => s.as_ref(),
173        }
174    }
175    /// Construct from a string-like value, matching known values.
176    pub fn from_value(s: S) -> Self {
177        match s.as_ref() {
178            "default" => Self::Default,
179            "gif" => Self::Gif,
180            _ => Self::Other(s),
181        }
182    }
183}
184
185impl<S: BosStr> core::fmt::Display for ViewPresentation<S> {
186    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
187        write!(f, "{}", self.as_str())
188    }
189}
190
191impl<S: BosStr> AsRef<str> for ViewPresentation<S> {
192    fn as_ref(&self) -> &str {
193        self.as_str()
194    }
195}
196
197impl<S: BosStr> Serialize for ViewPresentation<S> {
198    fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
199    where
200        Ser: serde::Serializer,
201    {
202        serializer.serialize_str(self.as_str())
203    }
204}
205
206impl<'de, S: Deserialize<'de> + BosStr> Deserialize<'de> for ViewPresentation<S> {
207    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
208    where
209        D: serde::Deserializer<'de>,
210    {
211        let s = S::deserialize(deserializer)?;
212        Ok(Self::from_value(s))
213    }
214}
215
216impl<S: BosStr + Default> Default for ViewPresentation<S> {
217    fn default() -> Self {
218        Self::Other(Default::default())
219    }
220}
221
222impl<S: BosStr> jacquard_common::IntoStatic for ViewPresentation<S>
223where
224    S: BosStr + jacquard_common::IntoStatic,
225    S::Output: BosStr,
226{
227    type Output = ViewPresentation<S::Output>;
228    fn into_static(self) -> Self::Output {
229        match self {
230            ViewPresentation::Default => ViewPresentation::Default,
231            ViewPresentation::Gif => ViewPresentation::Gif,
232            ViewPresentation::Other(v) => ViewPresentation::Other(v.into_static()),
233        }
234    }
235}
236
237impl<S: BosStr> LexiconSchema for Caption<S> {
238    fn nsid() -> &'static str {
239        "app.bsky.embed.video"
240    }
241    fn def_name() -> &'static str {
242        "caption"
243    }
244    fn lexicon_doc() -> LexiconDoc<'static> {
245        lexicon_doc_app_bsky_embed_video()
246    }
247    fn validate(&self) -> Result<(), ConstraintError> {
248        {
249            let value = &self.file;
250            {
251                let size = value.blob().size;
252                if size > 20000usize {
253                    return Err(ConstraintError::BlobTooLarge {
254                        path: ValidationPath::from_field("file"),
255                        max: 20000usize,
256                        actual: size,
257                    });
258                }
259            }
260        }
261        {
262            let value = &self.file;
263            {
264                let mime = value.blob().mime_type.as_str();
265                let accepted: &[&str] = &["text/vtt"];
266                let matched = accepted
267                    .iter()
268                    .any(|pattern| {
269                        if *pattern == "*/*" {
270                            true
271                        } else if pattern.ends_with("/*") {
272                            let prefix = &pattern[..pattern.len() - 2];
273                            mime.starts_with(prefix)
274                                && mime.as_bytes().get(prefix.len()) == Some(&b'/')
275                        } else {
276                            mime == *pattern
277                        }
278                    });
279                if !matched {
280                    return Err(ConstraintError::BlobMimeTypeNotAccepted {
281                        path: ValidationPath::from_field("file"),
282                        accepted: vec!["text/vtt".to_string()],
283                        actual: mime.to_string(),
284                    });
285                }
286            }
287        }
288        Ok(())
289    }
290}
291
292impl<S: BosStr> LexiconSchema for Video<S> {
293    fn nsid() -> &'static str {
294        "app.bsky.embed.video"
295    }
296    fn def_name() -> &'static str {
297        "main"
298    }
299    fn lexicon_doc() -> LexiconDoc<'static> {
300        lexicon_doc_app_bsky_embed_video()
301    }
302    fn validate(&self) -> Result<(), ConstraintError> {
303        if let Some(ref value) = self.alt {
304            #[allow(unused_comparisons)]
305            if <str>::len(value.as_ref()) > 10000usize {
306                return Err(ConstraintError::MaxLength {
307                    path: ValidationPath::from_field("alt"),
308                    max: 10000usize,
309                    actual: <str>::len(value.as_ref()),
310                });
311            }
312        }
313        if let Some(ref value) = self.alt {
314            {
315                let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count();
316                if count > 1000usize {
317                    return Err(ConstraintError::MaxGraphemes {
318                        path: ValidationPath::from_field("alt"),
319                        max: 1000usize,
320                        actual: count,
321                    });
322                }
323            }
324        }
325        if let Some(ref value) = self.captions {
326            #[allow(unused_comparisons)]
327            if value.len() > 20usize {
328                return Err(ConstraintError::MaxLength {
329                    path: ValidationPath::from_field("captions"),
330                    max: 20usize,
331                    actual: value.len(),
332                });
333            }
334        }
335        {
336            let value = &self.video;
337            {
338                let size = value.blob().size;
339                if size > 100000000usize {
340                    return Err(ConstraintError::BlobTooLarge {
341                        path: ValidationPath::from_field("video"),
342                        max: 100000000usize,
343                        actual: size,
344                    });
345                }
346            }
347        }
348        {
349            let value = &self.video;
350            {
351                let mime = value.blob().mime_type.as_str();
352                let accepted: &[&str] = &["video/mp4"];
353                let matched = accepted
354                    .iter()
355                    .any(|pattern| {
356                        if *pattern == "*/*" {
357                            true
358                        } else if pattern.ends_with("/*") {
359                            let prefix = &pattern[..pattern.len() - 2];
360                            mime.starts_with(prefix)
361                                && mime.as_bytes().get(prefix.len()) == Some(&b'/')
362                        } else {
363                            mime == *pattern
364                        }
365                    });
366                if !matched {
367                    return Err(ConstraintError::BlobMimeTypeNotAccepted {
368                        path: ValidationPath::from_field("video"),
369                        accepted: vec!["video/mp4".to_string()],
370                        actual: mime.to_string(),
371                    });
372                }
373            }
374        }
375        Ok(())
376    }
377}
378
379impl<S: BosStr> LexiconSchema for View<S> {
380    fn nsid() -> &'static str {
381        "app.bsky.embed.video"
382    }
383    fn def_name() -> &'static str {
384        "view"
385    }
386    fn lexicon_doc() -> LexiconDoc<'static> {
387        lexicon_doc_app_bsky_embed_video()
388    }
389    fn validate(&self) -> Result<(), ConstraintError> {
390        if let Some(ref value) = self.alt {
391            #[allow(unused_comparisons)]
392            if <str>::len(value.as_ref()) > 10000usize {
393                return Err(ConstraintError::MaxLength {
394                    path: ValidationPath::from_field("alt"),
395                    max: 10000usize,
396                    actual: <str>::len(value.as_ref()),
397                });
398            }
399        }
400        if let Some(ref value) = self.alt {
401            {
402                let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count();
403                if count > 1000usize {
404                    return Err(ConstraintError::MaxGraphemes {
405                        path: ValidationPath::from_field("alt"),
406                        max: 1000usize,
407                        actual: count,
408                    });
409                }
410            }
411        }
412        Ok(())
413    }
414}
415
416pub mod caption_state {
417
418    pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
419    #[allow(unused)]
420    use ::core::marker::PhantomData;
421    mod sealed {
422        pub trait Sealed {}
423    }
424    /// State trait tracking which required fields have been set
425    pub trait State: sealed::Sealed {
426        type File;
427        type Lang;
428    }
429    /// Empty state - all required fields are unset
430    pub struct Empty(());
431    impl sealed::Sealed for Empty {}
432    impl State for Empty {
433        type File = Unset;
434        type Lang = Unset;
435    }
436    ///State transition - sets the `file` field to Set
437    pub struct SetFile<St: State = Empty>(PhantomData<fn() -> St>);
438    impl<St: State> sealed::Sealed for SetFile<St> {}
439    impl<St: State> State for SetFile<St> {
440        type File = Set<members::file>;
441        type Lang = St::Lang;
442    }
443    ///State transition - sets the `lang` field to Set
444    pub struct SetLang<St: State = Empty>(PhantomData<fn() -> St>);
445    impl<St: State> sealed::Sealed for SetLang<St> {}
446    impl<St: State> State for SetLang<St> {
447        type File = St::File;
448        type Lang = Set<members::lang>;
449    }
450    /// Marker types for field names
451    #[allow(non_camel_case_types)]
452    pub mod members {
453        ///Marker type for the `file` field
454        pub struct file(());
455        ///Marker type for the `lang` field
456        pub struct lang(());
457    }
458}
459
460/// Builder for constructing an instance of this type.
461pub struct CaptionBuilder<St: caption_state::State, S: BosStr = DefaultStr> {
462    _state: PhantomData<fn() -> St>,
463    _fields: (Option<BlobRef<S>>, Option<Language>),
464    _type: PhantomData<fn() -> S>,
465}
466
467impl Caption<DefaultStr> {
468    /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed
469    pub fn new() -> CaptionBuilder<caption_state::Empty, DefaultStr> {
470        CaptionBuilder::new()
471    }
472}
473
474impl<S: BosStr> Caption<S> {
475    /// Create a new builder for this type
476    pub fn builder() -> CaptionBuilder<caption_state::Empty, S> {
477        CaptionBuilder::builder()
478    }
479}
480
481impl CaptionBuilder<caption_state::Empty, DefaultStr> {
482    /// Create a new builder with all fields unset, using the default string type, if needed
483    pub fn new() -> Self {
484        CaptionBuilder {
485            _state: PhantomData,
486            _fields: (None, None),
487            _type: PhantomData,
488        }
489    }
490}
491
492impl<S: BosStr> CaptionBuilder<caption_state::Empty, S> {
493    /// Create a new builder with all fields unset
494    pub fn builder() -> Self {
495        CaptionBuilder {
496            _state: PhantomData,
497            _fields: (None, None),
498            _type: PhantomData,
499        }
500    }
501}
502
503impl<St, S: BosStr> CaptionBuilder<St, S>
504where
505    St: caption_state::State,
506    St::File: caption_state::IsUnset,
507{
508    /// Set the `file` field (required)
509    pub fn file(
510        mut self,
511        value: impl Into<BlobRef<S>>,
512    ) -> CaptionBuilder<caption_state::SetFile<St>, S> {
513        self._fields.0 = Option::Some(value.into());
514        CaptionBuilder {
515            _state: PhantomData,
516            _fields: self._fields,
517            _type: PhantomData,
518        }
519    }
520}
521
522impl<St, S: BosStr> CaptionBuilder<St, S>
523where
524    St: caption_state::State,
525    St::Lang: caption_state::IsUnset,
526{
527    /// Set the `lang` field (required)
528    pub fn lang(
529        mut self,
530        value: impl Into<Language>,
531    ) -> CaptionBuilder<caption_state::SetLang<St>, S> {
532        self._fields.1 = Option::Some(value.into());
533        CaptionBuilder {
534            _state: PhantomData,
535            _fields: self._fields,
536            _type: PhantomData,
537        }
538    }
539}
540
541impl<St, S: BosStr> CaptionBuilder<St, S>
542where
543    St: caption_state::State,
544    St::File: caption_state::IsSet,
545    St::Lang: caption_state::IsSet,
546{
547    /// Build the final struct.
548    pub fn build(self) -> Caption<S> {
549        Caption {
550            file: self._fields.0.unwrap(),
551            lang: self._fields.1.unwrap(),
552            extra_data: Default::default(),
553        }
554    }
555    /// Build the final struct with custom extra_data.
556    pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> Caption<S> {
557        Caption {
558            file: self._fields.0.unwrap(),
559            lang: self._fields.1.unwrap(),
560            extra_data: Some(extra_data),
561        }
562    }
563}
564
565fn lexicon_doc_app_bsky_embed_video() -> LexiconDoc<'static> {
566    #[allow(unused_imports)]
567    use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
568    use jacquard_lexicon::lexicon::*;
569    use alloc::collections::BTreeMap;
570    LexiconDoc {
571        lexicon: Lexicon::Lexicon1,
572        id: CowStr::new_static("app.bsky.embed.video"),
573        defs: {
574            let mut map = BTreeMap::new();
575            map.insert(
576                SmolStr::new_static("caption"),
577                LexUserType::Object(LexObject {
578                    required: Some(
579                        vec![SmolStr::new_static("lang"), SmolStr::new_static("file")],
580                    ),
581                    properties: {
582                        #[allow(unused_mut)]
583                        let mut map = BTreeMap::new();
584                        map.insert(
585                            SmolStr::new_static("file"),
586                            LexObjectProperty::Blob(LexBlob { ..Default::default() }),
587                        );
588                        map.insert(
589                            SmolStr::new_static("lang"),
590                            LexObjectProperty::String(LexString {
591                                format: Some(LexStringFormat::Language),
592                                ..Default::default()
593                            }),
594                        );
595                        map
596                    },
597                    ..Default::default()
598                }),
599            );
600            map.insert(
601                SmolStr::new_static("main"),
602                LexUserType::Object(LexObject {
603                    required: Some(vec![SmolStr::new_static("video")]),
604                    properties: {
605                        #[allow(unused_mut)]
606                        let mut map = BTreeMap::new();
607                        map.insert(
608                            SmolStr::new_static("alt"),
609                            LexObjectProperty::String(LexString {
610                                description: Some(
611                                    CowStr::new_static(
612                                        "Alt text description of the video, for accessibility.",
613                                    ),
614                                ),
615                                max_length: Some(10000usize),
616                                max_graphemes: Some(1000usize),
617                                ..Default::default()
618                            }),
619                        );
620                        map.insert(
621                            SmolStr::new_static("aspectRatio"),
622                            LexObjectProperty::Ref(LexRef {
623                                r#ref: CowStr::new_static(
624                                    "app.bsky.embed.defs#aspectRatio",
625                                ),
626                                ..Default::default()
627                            }),
628                        );
629                        map.insert(
630                            SmolStr::new_static("captions"),
631                            LexObjectProperty::Array(LexArray {
632                                items: LexArrayItem::Ref(LexRef {
633                                    r#ref: CowStr::new_static("#caption"),
634                                    ..Default::default()
635                                }),
636                                max_length: Some(20usize),
637                                ..Default::default()
638                            }),
639                        );
640                        map.insert(
641                            SmolStr::new_static("presentation"),
642                            LexObjectProperty::String(LexString {
643                                description: Some(
644                                    CowStr::new_static(
645                                        "A hint to the client about how to present the video.",
646                                    ),
647                                ),
648                                ..Default::default()
649                            }),
650                        );
651                        map.insert(
652                            SmolStr::new_static("video"),
653                            LexObjectProperty::Blob(LexBlob { ..Default::default() }),
654                        );
655                        map
656                    },
657                    ..Default::default()
658                }),
659            );
660            map.insert(
661                SmolStr::new_static("view"),
662                LexUserType::Object(LexObject {
663                    required: Some(
664                        vec![SmolStr::new_static("cid"), SmolStr::new_static("playlist")],
665                    ),
666                    properties: {
667                        #[allow(unused_mut)]
668                        let mut map = BTreeMap::new();
669                        map.insert(
670                            SmolStr::new_static("alt"),
671                            LexObjectProperty::String(LexString {
672                                max_length: Some(10000usize),
673                                max_graphemes: Some(1000usize),
674                                ..Default::default()
675                            }),
676                        );
677                        map.insert(
678                            SmolStr::new_static("aspectRatio"),
679                            LexObjectProperty::Ref(LexRef {
680                                r#ref: CowStr::new_static(
681                                    "app.bsky.embed.defs#aspectRatio",
682                                ),
683                                ..Default::default()
684                            }),
685                        );
686                        map.insert(
687                            SmolStr::new_static("cid"),
688                            LexObjectProperty::String(LexString {
689                                format: Some(LexStringFormat::Cid),
690                                ..Default::default()
691                            }),
692                        );
693                        map.insert(
694                            SmolStr::new_static("playlist"),
695                            LexObjectProperty::String(LexString {
696                                format: Some(LexStringFormat::Uri),
697                                ..Default::default()
698                            }),
699                        );
700                        map.insert(
701                            SmolStr::new_static("presentation"),
702                            LexObjectProperty::String(LexString {
703                                description: Some(
704                                    CowStr::new_static(
705                                        "A hint to the client about how to present the video.",
706                                    ),
707                                ),
708                                ..Default::default()
709                            }),
710                        );
711                        map.insert(
712                            SmolStr::new_static("thumbnail"),
713                            LexObjectProperty::String(LexString {
714                                format: Some(LexStringFormat::Uri),
715                                ..Default::default()
716                            }),
717                        );
718                        map
719                    },
720                    ..Default::default()
721                }),
722            );
723            map
724        },
725        ..Default::default()
726    }
727}
728
729pub mod video_state {
730
731    pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
732    #[allow(unused)]
733    use ::core::marker::PhantomData;
734    mod sealed {
735        pub trait Sealed {}
736    }
737    /// State trait tracking which required fields have been set
738    pub trait State: sealed::Sealed {
739        type Video;
740    }
741    /// Empty state - all required fields are unset
742    pub struct Empty(());
743    impl sealed::Sealed for Empty {}
744    impl State for Empty {
745        type Video = Unset;
746    }
747    ///State transition - sets the `video` field to Set
748    pub struct SetVideo<St: State = Empty>(PhantomData<fn() -> St>);
749    impl<St: State> sealed::Sealed for SetVideo<St> {}
750    impl<St: State> State for SetVideo<St> {
751        type Video = Set<members::video>;
752    }
753    /// Marker types for field names
754    #[allow(non_camel_case_types)]
755    pub mod members {
756        ///Marker type for the `video` field
757        pub struct video(());
758    }
759}
760
761/// Builder for constructing an instance of this type.
762pub struct VideoBuilder<St: video_state::State, S: BosStr = DefaultStr> {
763    _state: PhantomData<fn() -> St>,
764    _fields: (
765        Option<S>,
766        Option<AspectRatio<S>>,
767        Option<Vec<video::Caption<S>>>,
768        Option<VideoPresentation<S>>,
769        Option<BlobRef<S>>,
770    ),
771    _type: PhantomData<fn() -> S>,
772}
773
774impl Video<DefaultStr> {
775    /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed
776    pub fn new() -> VideoBuilder<video_state::Empty, DefaultStr> {
777        VideoBuilder::new()
778    }
779}
780
781impl<S: BosStr> Video<S> {
782    /// Create a new builder for this type
783    pub fn builder() -> VideoBuilder<video_state::Empty, S> {
784        VideoBuilder::builder()
785    }
786}
787
788impl VideoBuilder<video_state::Empty, DefaultStr> {
789    /// Create a new builder with all fields unset, using the default string type, if needed
790    pub fn new() -> Self {
791        VideoBuilder {
792            _state: PhantomData,
793            _fields: (None, None, None, None, None),
794            _type: PhantomData,
795        }
796    }
797}
798
799impl<S: BosStr> VideoBuilder<video_state::Empty, S> {
800    /// Create a new builder with all fields unset
801    pub fn builder() -> Self {
802        VideoBuilder {
803            _state: PhantomData,
804            _fields: (None, None, None, None, None),
805            _type: PhantomData,
806        }
807    }
808}
809
810impl<St: video_state::State, S: BosStr> VideoBuilder<St, S> {
811    /// Set the `alt` field (optional)
812    pub fn alt(mut self, value: impl Into<Option<S>>) -> Self {
813        self._fields.0 = value.into();
814        self
815    }
816    /// Set the `alt` field to an Option value (optional)
817    pub fn maybe_alt(mut self, value: Option<S>) -> Self {
818        self._fields.0 = value;
819        self
820    }
821}
822
823impl<St: video_state::State, S: BosStr> VideoBuilder<St, S> {
824    /// Set the `aspectRatio` field (optional)
825    pub fn aspect_ratio(mut self, value: impl Into<Option<AspectRatio<S>>>) -> Self {
826        self._fields.1 = value.into();
827        self
828    }
829    /// Set the `aspectRatio` field to an Option value (optional)
830    pub fn maybe_aspect_ratio(mut self, value: Option<AspectRatio<S>>) -> Self {
831        self._fields.1 = value;
832        self
833    }
834}
835
836impl<St: video_state::State, S: BosStr> VideoBuilder<St, S> {
837    /// Set the `captions` field (optional)
838    pub fn captions(mut self, value: impl Into<Option<Vec<video::Caption<S>>>>) -> Self {
839        self._fields.2 = value.into();
840        self
841    }
842    /// Set the `captions` field to an Option value (optional)
843    pub fn maybe_captions(mut self, value: Option<Vec<video::Caption<S>>>) -> Self {
844        self._fields.2 = value;
845        self
846    }
847}
848
849impl<St: video_state::State, S: BosStr> VideoBuilder<St, S> {
850    /// Set the `presentation` field (optional)
851    pub fn presentation(
852        mut self,
853        value: impl Into<Option<VideoPresentation<S>>>,
854    ) -> Self {
855        self._fields.3 = value.into();
856        self
857    }
858    /// Set the `presentation` field to an Option value (optional)
859    pub fn maybe_presentation(mut self, value: Option<VideoPresentation<S>>) -> Self {
860        self._fields.3 = value;
861        self
862    }
863}
864
865impl<St, S: BosStr> VideoBuilder<St, S>
866where
867    St: video_state::State,
868    St::Video: video_state::IsUnset,
869{
870    /// Set the `video` field (required)
871    pub fn video(
872        mut self,
873        value: impl Into<BlobRef<S>>,
874    ) -> VideoBuilder<video_state::SetVideo<St>, S> {
875        self._fields.4 = Option::Some(value.into());
876        VideoBuilder {
877            _state: PhantomData,
878            _fields: self._fields,
879            _type: PhantomData,
880        }
881    }
882}
883
884impl<St, S: BosStr> VideoBuilder<St, S>
885where
886    St: video_state::State,
887    St::Video: video_state::IsSet,
888{
889    /// Build the final struct.
890    pub fn build(self) -> Video<S> {
891        Video {
892            alt: self._fields.0,
893            aspect_ratio: self._fields.1,
894            captions: self._fields.2,
895            presentation: self._fields.3,
896            video: self._fields.4.unwrap(),
897            extra_data: Default::default(),
898        }
899    }
900    /// Build the final struct with custom extra_data.
901    pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> Video<S> {
902        Video {
903            alt: self._fields.0,
904            aspect_ratio: self._fields.1,
905            captions: self._fields.2,
906            presentation: self._fields.3,
907            video: self._fields.4.unwrap(),
908            extra_data: Some(extra_data),
909        }
910    }
911}
912
913pub mod view_state {
914
915    pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
916    #[allow(unused)]
917    use ::core::marker::PhantomData;
918    mod sealed {
919        pub trait Sealed {}
920    }
921    /// State trait tracking which required fields have been set
922    pub trait State: sealed::Sealed {
923        type Cid;
924        type Playlist;
925    }
926    /// Empty state - all required fields are unset
927    pub struct Empty(());
928    impl sealed::Sealed for Empty {}
929    impl State for Empty {
930        type Cid = Unset;
931        type Playlist = Unset;
932    }
933    ///State transition - sets the `cid` field to Set
934    pub struct SetCid<St: State = Empty>(PhantomData<fn() -> St>);
935    impl<St: State> sealed::Sealed for SetCid<St> {}
936    impl<St: State> State for SetCid<St> {
937        type Cid = Set<members::cid>;
938        type Playlist = St::Playlist;
939    }
940    ///State transition - sets the `playlist` field to Set
941    pub struct SetPlaylist<St: State = Empty>(PhantomData<fn() -> St>);
942    impl<St: State> sealed::Sealed for SetPlaylist<St> {}
943    impl<St: State> State for SetPlaylist<St> {
944        type Cid = St::Cid;
945        type Playlist = Set<members::playlist>;
946    }
947    /// Marker types for field names
948    #[allow(non_camel_case_types)]
949    pub mod members {
950        ///Marker type for the `cid` field
951        pub struct cid(());
952        ///Marker type for the `playlist` field
953        pub struct playlist(());
954    }
955}
956
957/// Builder for constructing an instance of this type.
958pub struct ViewBuilder<St: view_state::State, S: BosStr = DefaultStr> {
959    _state: PhantomData<fn() -> St>,
960    _fields: (
961        Option<S>,
962        Option<AspectRatio<S>>,
963        Option<Cid<S>>,
964        Option<UriValue<S>>,
965        Option<ViewPresentation<S>>,
966        Option<UriValue<S>>,
967    ),
968    _type: PhantomData<fn() -> S>,
969}
970
971impl View<DefaultStr> {
972    /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed
973    pub fn new() -> ViewBuilder<view_state::Empty, DefaultStr> {
974        ViewBuilder::new()
975    }
976}
977
978impl<S: BosStr> View<S> {
979    /// Create a new builder for this type
980    pub fn builder() -> ViewBuilder<view_state::Empty, S> {
981        ViewBuilder::builder()
982    }
983}
984
985impl ViewBuilder<view_state::Empty, DefaultStr> {
986    /// Create a new builder with all fields unset, using the default string type, if needed
987    pub fn new() -> Self {
988        ViewBuilder {
989            _state: PhantomData,
990            _fields: (None, None, None, None, None, None),
991            _type: PhantomData,
992        }
993    }
994}
995
996impl<S: BosStr> ViewBuilder<view_state::Empty, S> {
997    /// Create a new builder with all fields unset
998    pub fn builder() -> Self {
999        ViewBuilder {
1000            _state: PhantomData,
1001            _fields: (None, None, None, None, None, None),
1002            _type: PhantomData,
1003        }
1004    }
1005}
1006
1007impl<St: view_state::State, S: BosStr> ViewBuilder<St, S> {
1008    /// Set the `alt` field (optional)
1009    pub fn alt(mut self, value: impl Into<Option<S>>) -> Self {
1010        self._fields.0 = value.into();
1011        self
1012    }
1013    /// Set the `alt` field to an Option value (optional)
1014    pub fn maybe_alt(mut self, value: Option<S>) -> Self {
1015        self._fields.0 = value;
1016        self
1017    }
1018}
1019
1020impl<St: view_state::State, S: BosStr> ViewBuilder<St, S> {
1021    /// Set the `aspectRatio` field (optional)
1022    pub fn aspect_ratio(mut self, value: impl Into<Option<AspectRatio<S>>>) -> Self {
1023        self._fields.1 = value.into();
1024        self
1025    }
1026    /// Set the `aspectRatio` field to an Option value (optional)
1027    pub fn maybe_aspect_ratio(mut self, value: Option<AspectRatio<S>>) -> Self {
1028        self._fields.1 = value;
1029        self
1030    }
1031}
1032
1033impl<St, S: BosStr> ViewBuilder<St, S>
1034where
1035    St: view_state::State,
1036    St::Cid: view_state::IsUnset,
1037{
1038    /// Set the `cid` field (required)
1039    pub fn cid(
1040        mut self,
1041        value: impl Into<Cid<S>>,
1042    ) -> ViewBuilder<view_state::SetCid<St>, S> {
1043        self._fields.2 = Option::Some(value.into());
1044        ViewBuilder {
1045            _state: PhantomData,
1046            _fields: self._fields,
1047            _type: PhantomData,
1048        }
1049    }
1050}
1051
1052impl<St, S: BosStr> ViewBuilder<St, S>
1053where
1054    St: view_state::State,
1055    St::Playlist: view_state::IsUnset,
1056{
1057    /// Set the `playlist` field (required)
1058    pub fn playlist(
1059        mut self,
1060        value: impl Into<UriValue<S>>,
1061    ) -> ViewBuilder<view_state::SetPlaylist<St>, S> {
1062        self._fields.3 = Option::Some(value.into());
1063        ViewBuilder {
1064            _state: PhantomData,
1065            _fields: self._fields,
1066            _type: PhantomData,
1067        }
1068    }
1069}
1070
1071impl<St: view_state::State, S: BosStr> ViewBuilder<St, S> {
1072    /// Set the `presentation` field (optional)
1073    pub fn presentation(
1074        mut self,
1075        value: impl Into<Option<ViewPresentation<S>>>,
1076    ) -> Self {
1077        self._fields.4 = value.into();
1078        self
1079    }
1080    /// Set the `presentation` field to an Option value (optional)
1081    pub fn maybe_presentation(mut self, value: Option<ViewPresentation<S>>) -> Self {
1082        self._fields.4 = value;
1083        self
1084    }
1085}
1086
1087impl<St: view_state::State, S: BosStr> ViewBuilder<St, S> {
1088    /// Set the `thumbnail` field (optional)
1089    pub fn thumbnail(mut self, value: impl Into<Option<UriValue<S>>>) -> Self {
1090        self._fields.5 = value.into();
1091        self
1092    }
1093    /// Set the `thumbnail` field to an Option value (optional)
1094    pub fn maybe_thumbnail(mut self, value: Option<UriValue<S>>) -> Self {
1095        self._fields.5 = value;
1096        self
1097    }
1098}
1099
1100impl<St, S: BosStr> ViewBuilder<St, S>
1101where
1102    St: view_state::State,
1103    St::Cid: view_state::IsSet,
1104    St::Playlist: view_state::IsSet,
1105{
1106    /// Build the final struct.
1107    pub fn build(self) -> View<S> {
1108        View {
1109            alt: self._fields.0,
1110            aspect_ratio: self._fields.1,
1111            cid: self._fields.2.unwrap(),
1112            playlist: self._fields.3.unwrap(),
1113            presentation: self._fields.4,
1114            thumbnail: self._fields.5,
1115            extra_data: Default::default(),
1116        }
1117    }
1118    /// Build the final struct with custom extra_data.
1119    pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> View<S> {
1120        View {
1121            alt: self._fields.0,
1122            aspect_ratio: self._fields.1,
1123            cid: self._fields.2.unwrap(),
1124            playlist: self._fields.3.unwrap(),
1125            presentation: self._fields.4,
1126            thumbnail: self._fields.5,
1127            extra_data: Some(extra_data),
1128        }
1129    }
1130}