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