| |
| |
| |
| |
| |
|
|
| use crate::data::*; |
| use crate::bex_all_generated::bex::wire as wire; |
|
|
| |
| |
| |
|
|
| |
| fn build_image<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &ImageData, |
| ) -> flatbuffers::WIPOffset<wire::Image<'a>> { |
| let url = if !data.url.is_empty() { |
| Some(fbb.create_string(&data.url)) |
| } else { |
| None |
| }; |
| let layout = if !data.layout.is_empty() { |
| Some(fbb.create_string(&data.layout)) |
| } else { |
| None |
| }; |
| let blurhash = data.blurhash.as_ref().map(|s| fbb.create_string(s)); |
|
|
| wire::Image::create( |
| fbb, |
| &wire::ImageArgs { |
| url, |
| layout, |
| width: data.width, |
| height: data.height, |
| blurhash, |
| }, |
| ) |
| } |
|
|
| |
| fn build_image_set<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &ImageSetData, |
| ) -> flatbuffers::WIPOffset<wire::ImageSet<'a>> { |
| let low = data.low.as_ref().map(|d| build_image(fbb, d)); |
| let medium = data.medium.as_ref().map(|d| build_image(fbb, d)); |
| let high = data.high.as_ref().map(|d| build_image(fbb, d)); |
| let backdrop = data.backdrop.as_ref().map(|d| build_image(fbb, d)); |
| let logo = data.logo.as_ref().map(|d| build_image(fbb, d)); |
|
|
| wire::ImageSet::create( |
| fbb, |
| &wire::ImageSetArgs { |
| low, |
| medium, |
| high, |
| backdrop, |
| logo, |
| }, |
| ) |
| } |
|
|
| |
| fn build_linked_id<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &LinkedIdData, |
| ) -> flatbuffers::WIPOffset<wire::LinkedId<'a>> { |
| let source = if !data.source.is_empty() { |
| Some(fbb.create_string(&data.source)) |
| } else { |
| None |
| }; |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
|
|
| wire::LinkedId::create(fbb, &wire::LinkedIdArgs { source, id }) |
| } |
|
|
| |
| fn build_attr<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &AttrData, |
| ) -> flatbuffers::WIPOffset<wire::Attr<'a>> { |
| let key = if !data.key.is_empty() { |
| Some(fbb.create_string(&data.key)) |
| } else { |
| None |
| }; |
| let value = if !data.value.is_empty() { |
| Some(fbb.create_string(&data.value)) |
| } else { |
| None |
| }; |
|
|
| wire::Attr::create(fbb, &wire::AttrArgs { key, value }) |
| } |
|
|
| |
| fn build_attr_vec<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| items: &[AttrData], |
| ) -> flatbuffers::WIPOffset< |
| flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<wire::Attr<'a>>>, |
| > { |
| let offsets: Vec<_> = items.iter().map(|d| build_attr(fbb, d)).collect(); |
| fbb.create_vector(&offsets) |
| } |
|
|
| |
| fn build_string_vec<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| items: &[String], |
| ) -> flatbuffers::WIPOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>> |
| { |
| let offsets: Vec<_> = items.iter().map(|s| fbb.create_string(s)).collect(); |
| fbb.create_vector(&offsets) |
| } |
|
|
| |
| fn build_linked_id_vec<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| items: &[LinkedIdData], |
| ) -> flatbuffers::WIPOffset< |
| flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<wire::LinkedId<'a>>>, |
| > { |
| let offsets: Vec<_> = items.iter().map(|d| build_linked_id(fbb, d)).collect(); |
| fbb.create_vector(&offsets) |
| } |
|
|
| |
| |
| |
|
|
| |
| fn build_media_card<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &MediaCardData, |
| ) -> flatbuffers::WIPOffset<wire::MediaCard<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let title = if !data.title.is_empty() { |
| Some(fbb.create_string(&data.title)) |
| } else { |
| None |
| }; |
| let images = data.images.as_ref().map(|d| build_image_set(fbb, d)); |
| let original_title = data.original_title.as_ref().map(|s| fbb.create_string(s)); |
| let tagline = data.tagline.as_ref().map(|s| fbb.create_string(s)); |
| let year = data.year.as_ref().map(|s| fbb.create_string(s)); |
| let genres = if !data.genres.is_empty() { |
| Some(build_string_vec(fbb, &data.genres)) |
| } else { |
| None |
| }; |
| let content_rating = data.content_rating.as_ref().map(|s| fbb.create_string(s)); |
| let url = data.url.as_ref().map(|s| fbb.create_string(s)); |
| let ids = if !data.ids.is_empty() { |
| Some(build_linked_id_vec(fbb, &data.ids)) |
| } else { |
| None |
| }; |
| let extra = if !data.extra.is_empty() { |
| Some(build_attr_vec(fbb, &data.extra)) |
| } else { |
| None |
| }; |
|
|
| wire::MediaCard::create( |
| fbb, |
| &wire::MediaCardArgs { |
| id, |
| title, |
| kind: wire::MediaKind(data.kind as i8), |
| images, |
| original_title, |
| tagline, |
| year, |
| score: data.score, |
| genres, |
| status: wire::Status(data.status as i8), |
| content_rating, |
| url, |
| ids, |
| extra, |
| }, |
| ) |
| } |
|
|
| |
| fn build_category_link<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &CategoryLinkData, |
| ) -> flatbuffers::WIPOffset<wire::CategoryLink<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let title = if !data.title.is_empty() { |
| Some(fbb.create_string(&data.title)) |
| } else { |
| None |
| }; |
| let subtitle = data.subtitle.as_ref().map(|s| fbb.create_string(s)); |
| let image = data.image.as_ref().map(|d| build_image(fbb, d)); |
|
|
| wire::CategoryLink::create( |
| fbb, |
| &wire::CategoryLinkArgs { |
| id, |
| title, |
| subtitle, |
| image, |
| }, |
| ) |
| } |
|
|
| |
| fn build_episode<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &EpisodeData, |
| ) -> flatbuffers::WIPOffset<wire::Episode<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let title = if !data.title.is_empty() { |
| Some(fbb.create_string(&data.title)) |
| } else { |
| None |
| }; |
| let images = data.images.as_ref().map(|d| build_image_set(fbb, d)); |
| let description = data.description.as_ref().map(|s| fbb.create_string(s)); |
| let released = data.released.as_ref().map(|s| fbb.create_string(s)); |
| let url = data.url.as_ref().map(|s| fbb.create_string(s)); |
| let tags = if !data.tags.is_empty() { |
| Some(build_string_vec(fbb, &data.tags)) |
| } else { |
| None |
| }; |
| let extra = if !data.extra.is_empty() { |
| Some(build_attr_vec(fbb, &data.extra)) |
| } else { |
| None |
| }; |
|
|
| wire::Episode::create( |
| fbb, |
| &wire::EpisodeArgs { |
| id, |
| title, |
| number: data.number, |
| season: data.season, |
| images, |
| description, |
| released, |
| score: data.score, |
| url, |
| tags, |
| extra, |
| }, |
| ) |
| } |
|
|
| |
| fn build_season<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &SeasonData, |
| ) -> flatbuffers::WIPOffset<wire::Season<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let title = if !data.title.is_empty() { |
| Some(fbb.create_string(&data.title)) |
| } else { |
| None |
| }; |
| let episodes = if !data.episodes.is_empty() { |
| let offsets: Vec<_> = data.episodes.iter().map(|d| build_episode(fbb, d)).collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
|
|
| wire::Season::create( |
| fbb, |
| &wire::SeasonArgs { |
| id, |
| title, |
| number: data.number, |
| year: data.year, |
| episodes, |
| }, |
| ) |
| } |
|
|
| |
| fn build_person<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &PersonData, |
| ) -> flatbuffers::WIPOffset<wire::Person<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let name = if !data.name.is_empty() { |
| Some(fbb.create_string(&data.name)) |
| } else { |
| None |
| }; |
| let image = data.image.as_ref().map(|d| build_image_set(fbb, d)); |
| let role = data.role.as_ref().map(|s| fbb.create_string(s)); |
| let url = data.url.as_ref().map(|s| fbb.create_string(s)); |
|
|
| wire::Person::create( |
| fbb, |
| &wire::PersonArgs { |
| id, |
| name, |
| image, |
| role, |
| url, |
| }, |
| ) |
| } |
|
|
| |
| fn build_media_info<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &MediaInfoData, |
| ) -> flatbuffers::WIPOffset<wire::MediaInfo<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let title = if !data.title.is_empty() { |
| Some(fbb.create_string(&data.title)) |
| } else { |
| None |
| }; |
| let images = data.images.as_ref().map(|d| build_image_set(fbb, d)); |
| let original_title = data.original_title.as_ref().map(|s| fbb.create_string(s)); |
| let description = data.description.as_ref().map(|s| fbb.create_string(s)); |
| let year = data.year.as_ref().map(|s| fbb.create_string(s)); |
| let release_date = data.release_date.as_ref().map(|s| fbb.create_string(s)); |
| let genres = if !data.genres.is_empty() { |
| Some(build_string_vec(fbb, &data.genres)) |
| } else { |
| None |
| }; |
| let tags = if !data.tags.is_empty() { |
| Some(build_string_vec(fbb, &data.tags)) |
| } else { |
| None |
| }; |
| let content_rating = data.content_rating.as_ref().map(|s| fbb.create_string(s)); |
| let seasons = if !data.seasons.is_empty() { |
| let offsets: Vec<_> = data.seasons.iter().map(|d| build_season(fbb, d)).collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let cast = if !data.cast.is_empty() { |
| let offsets: Vec<_> = data.cast.iter().map(|d| build_person(fbb, d)).collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let crew = if !data.crew.is_empty() { |
| let offsets: Vec<_> = data.crew.iter().map(|d| build_person(fbb, d)).collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let trailer_url = data.trailer_url.as_ref().map(|s| fbb.create_string(s)); |
| let ids = if !data.ids.is_empty() { |
| Some(build_linked_id_vec(fbb, &data.ids)) |
| } else { |
| None |
| }; |
| let studio = data.studio.as_ref().map(|s| fbb.create_string(s)); |
| let country = data.country.as_ref().map(|s| fbb.create_string(s)); |
| let language = data.language.as_ref().map(|s| fbb.create_string(s)); |
| let url = data.url.as_ref().map(|s| fbb.create_string(s)); |
| let extra = if !data.extra.is_empty() { |
| Some(build_attr_vec(fbb, &data.extra)) |
| } else { |
| None |
| }; |
|
|
| wire::MediaInfo::create( |
| fbb, |
| &wire::MediaInfoArgs { |
| id, |
| title, |
| kind: wire::MediaKind(data.kind as i8), |
| images, |
| original_title, |
| description, |
| score: data.score, |
| scored_by: data.scored_by, |
| year, |
| release_date, |
| genres, |
| tags, |
| status: wire::Status(data.status as i8), |
| content_rating, |
| seasons, |
| cast, |
| crew, |
| runtime_minutes: data.runtime_minutes, |
| trailer_url, |
| ids, |
| studio, |
| country, |
| language, |
| url, |
| extra, |
| }, |
| ) |
| } |
|
|
| |
| fn build_home_section<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &HomeSectionData, |
| ) -> flatbuffers::WIPOffset<wire::HomeSection<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let title = if !data.title.is_empty() { |
| Some(fbb.create_string(&data.title)) |
| } else { |
| None |
| }; |
| let subtitle = data.subtitle.as_ref().map(|s| fbb.create_string(s)); |
| let items = if !data.items.is_empty() { |
| let offsets: Vec<_> = data.items.iter().map(|d| build_media_card(fbb, d)).collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let next_page = data.next_page.as_ref().map(|s| fbb.create_string(s)); |
| let layout = data.layout.as_ref().map(|s| fbb.create_string(s)); |
| let categories = if !data.categories.is_empty() { |
| let offsets: Vec<_> = data |
| .categories |
| .iter() |
| .map(|d| build_category_link(fbb, d)) |
| .collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let extra = if !data.extra.is_empty() { |
| Some(build_attr_vec(fbb, &data.extra)) |
| } else { |
| None |
| }; |
|
|
| wire::HomeSection::create( |
| fbb, |
| &wire::HomeSectionArgs { |
| id, |
| title, |
| subtitle, |
| items, |
| next_page, |
| layout, |
| show_rank: data.show_rank, |
| categories, |
| extra, |
| }, |
| ) |
| } |
|
|
| |
| |
| |
|
|
| |
| fn build_video_resolution<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &VideoResolutionData, |
| ) -> flatbuffers::WIPOffset<wire::VideoResolution<'a>> { |
| let label = data.label.as_ref().map(|s| fbb.create_string(s)); |
|
|
| wire::VideoResolution::create( |
| fbb, |
| &wire::VideoResolutionArgs { |
| width: data.width, |
| height: data.height, |
| hdr: data.hdr, |
| label, |
| }, |
| ) |
| } |
|
|
| |
| fn build_video_track<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &VideoTrackData, |
| ) -> flatbuffers::WIPOffset<wire::VideoTrack<'a>> { |
| let resolution = data.resolution.as_ref().map(|d| build_video_resolution(fbb, d)); |
| let url = if !data.url.is_empty() { |
| Some(fbb.create_string(&data.url)) |
| } else { |
| None |
| }; |
| let mime_type = data.mime_type.as_ref().map(|s| fbb.create_string(s)); |
| let codecs = data.codecs.as_ref().map(|s| fbb.create_string(s)); |
|
|
| wire::VideoTrack::create( |
| fbb, |
| &wire::VideoTrackArgs { |
| resolution, |
| url, |
| mime_type, |
| bitrate: data.bitrate, |
| codecs, |
| }, |
| ) |
| } |
|
|
| |
| fn build_subtitle_track<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &SubtitleTrackData, |
| ) -> flatbuffers::WIPOffset<wire::SubtitleTrack<'a>> { |
| let label = data.label.as_ref().map(|s| fbb.create_string(s)); |
| let url = if !data.url.is_empty() { |
| Some(fbb.create_string(&data.url)) |
| } else { |
| None |
| }; |
| let language = data.language.as_ref().map(|s| fbb.create_string(s)); |
| let format = data.format.as_ref().map(|s| fbb.create_string(s)); |
|
|
| wire::SubtitleTrack::create( |
| fbb, |
| &wire::SubtitleTrackArgs { |
| label, |
| url, |
| language, |
| format, |
| }, |
| ) |
| } |
|
|
| |
| fn build_server<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &ServerData, |
| ) -> flatbuffers::WIPOffset<wire::Server<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let label = data.label.as_ref().map(|s| fbb.create_string(s)); |
| let url = data.url.as_ref().map(|s| fbb.create_string(s)); |
| let extra = if !data.extra.is_empty() { |
| Some(build_attr_vec(fbb, &data.extra)) |
| } else { |
| None |
| }; |
|
|
| wire::Server::create( |
| fbb, |
| &wire::ServerArgs { |
| id, |
| label, |
| url, |
| priority: data.priority, |
| extra, |
| }, |
| ) |
| } |
|
|
| |
| fn build_stream_source<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| data: &StreamSourceData, |
| ) -> flatbuffers::WIPOffset<wire::StreamSource<'a>> { |
| let id = if !data.id.is_empty() { |
| Some(fbb.create_string(&data.id)) |
| } else { |
| None |
| }; |
| let label = data.label.as_ref().map(|s| fbb.create_string(s)); |
| let manifest_url = data.manifest_url.as_ref().map(|s| fbb.create_string(s)); |
| let videos = if !data.videos.is_empty() { |
| let offsets: Vec<_> = data.videos.iter().map(|d| build_video_track(fbb, d)).collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let subtitles = if !data.subtitles.is_empty() { |
| let offsets: Vec<_> = data |
| .subtitles |
| .iter() |
| .map(|d| build_subtitle_track(fbb, d)) |
| .collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let headers = if !data.headers.is_empty() { |
| Some(build_attr_vec(fbb, &data.headers)) |
| } else { |
| None |
| }; |
| let extra = if !data.extra.is_empty() { |
| Some(build_attr_vec(fbb, &data.extra)) |
| } else { |
| None |
| }; |
|
|
| wire::StreamSource::create( |
| fbb, |
| &wire::StreamSourceArgs { |
| id, |
| label, |
| format: wire::StreamFormat(data.format as i8), |
| manifest_url, |
| videos, |
| subtitles, |
| headers, |
| extra, |
| }, |
| ) |
| } |
|
|
| |
| fn build_paged_result<'a>( |
| fbb: &mut flatbuffers::FlatBufferBuilder<'a>, |
| items: &[MediaCardData], |
| categories: &[CategoryLinkData], |
| next_page: Option<&str>, |
| ) -> flatbuffers::WIPOffset<wire::PagedResult<'a>> { |
| let items_vec = if !items.is_empty() { |
| let offsets: Vec<_> = items.iter().map(|d| build_media_card(fbb, d)).collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let categories_vec = if !categories.is_empty() { |
| let offsets: Vec<_> = categories |
| .iter() |
| .map(|d| build_category_link(fbb, d)) |
| .collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
| let next_page_fb = next_page.map(|s| fbb.create_string(s)); |
|
|
| wire::PagedResult::create( |
| fbb, |
| &wire::PagedResultArgs { |
| items: items_vec, |
| categories: categories_vec, |
| next_page: next_page_fb, |
| }, |
| ) |
| } |
|
|
| |
| |
| |
|
|
| |
| pub fn build_home_result(sections: Vec<HomeSectionData>) -> Vec<u8> { |
| let mut fbb = flatbuffers::FlatBufferBuilder::new(); |
|
|
| let sections_vec = if !sections.is_empty() { |
| let offsets: Vec<_> = sections |
| .iter() |
| .map(|d| build_home_section(&mut fbb, d)) |
| .collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
|
|
| let root = wire::HomeResult::create( |
| &mut fbb, |
| &wire::HomeResultArgs { |
| sections: sections_vec, |
| }, |
| ); |
|
|
| fbb.finish(root, None); |
| fbb.finished_data().to_vec() |
| } |
|
|
| |
| pub fn build_search_result(items: Vec<MediaCardData>, next_page: Option<String>) -> Vec<u8> { |
| let mut fbb = flatbuffers::FlatBufferBuilder::new(); |
|
|
| let paged = build_paged_result(&mut fbb, &items, &[], next_page.as_deref()); |
|
|
| let root = wire::SearchResult::create( |
| &mut fbb, |
| &wire::SearchResultArgs { |
| result: Some(paged), |
| }, |
| ); |
|
|
| fbb.finish(root, None); |
| fbb.finished_data().to_vec() |
| } |
|
|
| |
| pub fn build_info_result(info: MediaInfoData) -> Vec<u8> { |
| let mut fbb = flatbuffers::FlatBufferBuilder::new(); |
|
|
| let info_fb = build_media_info(&mut fbb, &info); |
|
|
| let root = wire::InfoResult::create( |
| &mut fbb, |
| &wire::InfoResultArgs { |
| info: Some(info_fb), |
| }, |
| ); |
|
|
| fbb.finish(root, None); |
| fbb.finished_data().to_vec() |
| } |
|
|
| |
| pub fn build_servers_result(servers: Vec<ServerData>) -> Vec<u8> { |
| let mut fbb = flatbuffers::FlatBufferBuilder::new(); |
|
|
| let servers_vec = if !servers.is_empty() { |
| let offsets: Vec<_> = servers.iter().map(|d| build_server(&mut fbb, d)).collect(); |
| Some(fbb.create_vector(&offsets)) |
| } else { |
| None |
| }; |
|
|
| let root = wire::ServersResult::create( |
| &mut fbb, |
| &wire::ServersResultArgs { |
| servers: servers_vec, |
| }, |
| ); |
|
|
| fbb.finish(root, None); |
| fbb.finished_data().to_vec() |
| } |
|
|
| |
| pub fn build_stream_result(source: StreamSourceData) -> Vec<u8> { |
| let mut fbb = flatbuffers::FlatBufferBuilder::new(); |
|
|
| let source_fb = build_stream_source(&mut fbb, &source); |
|
|
| let root = wire::StreamResult::create( |
| &mut fbb, |
| &wire::StreamResultArgs { |
| source: Some(source_fb), |
| }, |
| ); |
|
|
| fbb.finish(root, None); |
| fbb.finished_data().to_vec() |
| } |
|
|
| |
| pub fn build_error_info(code: &str, message: &str, plugin_id: &str, request_id: u64) -> Vec<u8> { |
| let mut fbb = flatbuffers::FlatBufferBuilder::new(); |
|
|
| let code_fb = if !code.is_empty() { |
| Some(fbb.create_string(code)) |
| } else { |
| None |
| }; |
| let message_fb = if !message.is_empty() { |
| Some(fbb.create_string(message)) |
| } else { |
| None |
| }; |
| let plugin_id_fb = if !plugin_id.is_empty() { |
| Some(fbb.create_string(plugin_id)) |
| } else { |
| None |
| }; |
|
|
| let root = wire::ErrorInfo::create( |
| &mut fbb, |
| &wire::ErrorInfoArgs { |
| code: code_fb, |
| message: message_fb, |
| plugin_id: plugin_id_fb, |
| request_id, |
| }, |
| ); |
|
|
| fbb.finish(root, None); |
| fbb.finished_data().to_vec() |
| } |
|
|
| |
| |
| |
|
|
| #[cfg(test)] |
| mod tests { |
| use super::*; |
|
|
| #[test] |
| fn test_build_error_info() { |
| let buf = build_error_info("NOT_FOUND", "item missing", "plugin-1", 42); |
| let parsed = flatbuffers::root::<wire::ErrorInfo>(&buf).unwrap(); |
| assert_eq!(parsed.code().unwrap(), "NOT_FOUND"); |
| assert_eq!(parsed.message().unwrap(), "item missing"); |
| assert_eq!(parsed.plugin_id().unwrap(), "plugin-1"); |
| assert_eq!(parsed.request_id(), 42); |
| } |
|
|
| #[test] |
| fn test_build_home_result_empty() { |
| let buf = build_home_result(vec![]); |
| let parsed = wire::root_as_home_result(&buf).unwrap(); |
| assert!(parsed.sections().is_none()); |
| } |
|
|
| #[test] |
| fn test_build_home_result_with_section() { |
| let section = HomeSectionData { |
| id: "sec-1".into(), |
| title: "Trending".into(), |
| show_rank: true, |
| items: vec![MediaCardData { |
| id: "mc-1".into(), |
| title: "Test Movie".into(), |
| kind: 0, |
| score: 85, |
| ..Default::default() |
| }], |
| ..Default::default() |
| }; |
| let buf = build_home_result(vec![section]); |
| let parsed = wire::root_as_home_result(&buf).unwrap(); |
| let sections = parsed.sections().unwrap(); |
| assert_eq!(sections.len(), 1); |
| let s = sections.get(0); |
| assert_eq!(s.id().unwrap(), "sec-1"); |
| assert_eq!(s.title().unwrap(), "Trending"); |
| assert!(s.show_rank()); |
| let items = s.items().unwrap(); |
| assert_eq!(items.len(), 1); |
| assert_eq!(items.get(0).id().unwrap(), "mc-1"); |
| assert_eq!(items.get(0).title().unwrap(), "Test Movie"); |
| assert_eq!(items.get(0).score(), 85); |
| } |
|
|
| #[test] |
| fn test_build_search_result() { |
| let buf = build_search_result( |
| vec![MediaCardData { |
| id: "s-1".into(), |
| title: "Search Hit".into(), |
| kind: 1, |
| ..Default::default() |
| }], |
| Some("page2".into()), |
| ); |
| let parsed = flatbuffers::root::<wire::SearchResult>(&buf).unwrap(); |
| let paged = parsed.result().unwrap(); |
| assert_eq!(paged.next_page().unwrap(), "page2"); |
| let items = paged.items().unwrap(); |
| assert_eq!(items.len(), 1); |
| assert_eq!(items.get(0).id().unwrap(), "s-1"); |
| } |
|
|
| #[test] |
| fn test_build_servers_result() { |
| let buf = build_servers_result(vec![ServerData { |
| id: "svr-1".into(), |
| label: Some("HD Server".into()), |
| priority: 1, |
| ..Default::default() |
| }]); |
| let parsed = flatbuffers::root::<wire::ServersResult>(&buf).unwrap(); |
| let servers = parsed.servers().unwrap(); |
| assert_eq!(servers.len(), 1); |
| assert_eq!(servers.get(0).id().unwrap(), "svr-1"); |
| assert_eq!(servers.get(0).label().unwrap(), "HD Server"); |
| assert_eq!(servers.get(0).priority(), 1); |
| } |
|
|
| #[test] |
| fn test_build_stream_result() { |
| let buf = build_stream_result(StreamSourceData { |
| id: "src-1".into(), |
| label: Some("Main".into()), |
| format: 0, |
| manifest_url: Some("https://example.com/manifest.m3u8".into()), |
| videos: vec![VideoTrackData { |
| url: "https://example.com/video.mp4".into(), |
| bitrate: 5000, |
| ..Default::default() |
| }], |
| subtitles: vec![SubtitleTrackData { |
| url: "https://example.com/sub.vtt".into(), |
| language: Some("en".into()), |
| ..Default::default() |
| }], |
| ..Default::default() |
| }); |
| let parsed = flatbuffers::root::<wire::StreamResult>(&buf).unwrap(); |
| let source = parsed.source().unwrap(); |
| assert_eq!(source.id().unwrap(), "src-1"); |
| assert_eq!(source.format(), wire::StreamFormat::Hls); |
| assert_eq!( |
| source.manifest_url().unwrap(), |
| "https://example.com/manifest.m3u8" |
| ); |
| let videos = source.videos().unwrap(); |
| assert_eq!(videos.len(), 1); |
| assert_eq!(videos.get(0).bitrate(), 5000); |
| let subs = source.subtitles().unwrap(); |
| assert_eq!(subs.len(), 1); |
| assert_eq!(subs.get(0).language().unwrap(), "en"); |
| } |
|
|
| #[test] |
| fn test_build_info_result() { |
| let buf = build_info_result(MediaInfoData { |
| id: "info-1".into(), |
| title: "Detailed Info".into(), |
| kind: 0, |
| description: Some("A great movie".into()), |
| seasons: vec![SeasonData { |
| id: "s1".into(), |
| title: "Season 1".into(), |
| number: 1.0, |
| year: 2024, |
| episodes: vec![EpisodeData { |
| id: "ep1".into(), |
| title: "Pilot".into(), |
| number: 1.0, |
| season: 1.0, |
| ..Default::default() |
| }], |
| }], |
| ..Default::default() |
| }); |
| let parsed = flatbuffers::root::<wire::InfoResult>(&buf).unwrap(); |
| let info = parsed.info().unwrap(); |
| assert_eq!(info.id().unwrap(), "info-1"); |
| assert_eq!(info.description().unwrap(), "A great movie"); |
| let seasons = info.seasons().unwrap(); |
| assert_eq!(seasons.len(), 1); |
| let s = seasons.get(0); |
| assert_eq!(s.title().unwrap(), "Season 1"); |
| let episodes = s.episodes().unwrap(); |
| assert_eq!(episodes.len(), 1); |
| assert_eq!(episodes.get(0).title().unwrap(), "Pilot"); |
| } |
|
|
| #[test] |
| fn test_build_with_images_and_ids() { |
| let buf = build_search_result( |
| vec![MediaCardData { |
| id: "img-1".into(), |
| title: "With Images".into(), |
| kind: 0, |
| images: Some(ImageSetData { |
| low: Some(ImageData { |
| url: "https://img.low".into(), |
| layout: "portrait".into(), |
| width: 200, |
| height: 300, |
| blurhash: Some("LEHV6nWB2yk8pyo0".into()), |
| }), |
| ..Default::default() |
| }), |
| ids: vec![LinkedIdData { |
| source: "imdb".into(), |
| id: "tt1234567".into(), |
| }], |
| extra: vec![AttrData { |
| key: "rating".into(), |
| value: "R".into(), |
| }], |
| ..Default::default() |
| }], |
| None, |
| ); |
| let parsed = flatbuffers::root::<wire::SearchResult>(&buf).unwrap(); |
| let card = parsed.result().unwrap().items().unwrap().get(0); |
| assert_eq!(card.id().unwrap(), "img-1"); |
|
|
| let images = card.images().unwrap(); |
| let low = images.low().unwrap(); |
| assert_eq!(low.url().unwrap(), "https://img.low"); |
| assert_eq!(low.layout().unwrap(), "portrait"); |
| assert_eq!(low.width(), 200); |
| assert_eq!(low.height(), 300); |
| assert_eq!(low.blurhash().unwrap(), "LEHV6nWB2yk8pyo0"); |
|
|
| let ids = card.ids().unwrap(); |
| assert_eq!(ids.len(), 1); |
| assert_eq!(ids.get(0).source().unwrap(), "imdb"); |
| assert_eq!(ids.get(0).id().unwrap(), "tt1234567"); |
|
|
| let extra = card.extra().unwrap(); |
| assert_eq!(extra.len(), 1); |
| assert_eq!(extra.get(0).key().unwrap(), "rating"); |
| assert_eq!(extra.get(0).value().unwrap(), "R"); |
| } |
| } |
|
|