use live_data::{FeedDescriptor, FeedManifest, FormatPreference, TransportTag};
#[derive(Debug, Clone)]
pub struct FeedCatalog {
manifest: FeedManifest,
}
impl FeedCatalog {
pub fn new(manifest: FeedManifest) -> Self {
Self { manifest }
}
pub fn from_json(bytes: &[u8]) -> serde_json::Result<Self> {
let manifest = serde_json::from_slice(bytes)?;
Ok(Self::new(manifest))
}
pub fn from_json_str(s: &str) -> serde_json::Result<Self> {
Self::from_json(s.as_bytes())
}
pub fn manifest(&self) -> &FeedManifest {
&self.manifest
}
pub fn into_manifest(self) -> FeedManifest {
self.manifest
}
pub fn protocol_version(&self) -> u32 {
self.manifest.protocol_version
}
pub fn server_version(&self) -> &str {
&self.manifest.server_version
}
pub fn feeds(&self) -> &[FeedDescriptor] {
&self.manifest.feeds
}
pub fn len(&self) -> usize {
self.manifest.feeds.len()
}
pub fn is_empty(&self) -> bool {
self.manifest.feeds.is_empty()
}
pub fn find(&self, name: &str) -> Option<&FeedDescriptor> {
self.manifest.feeds.iter().find(|f| f.name == name)
}
pub fn filter_by_tag<'a>(
&'a self,
tag: &'a str,
) -> impl Iterator<Item = &'a FeedDescriptor> + 'a {
self.manifest
.feeds
.iter()
.filter(move |f| f.tags.iter().any(|t| t == tag))
}
pub fn filter_by_transport(
&self,
t: TransportTag,
) -> impl Iterator<Item = &FeedDescriptor> {
self.manifest.feeds.iter().filter(move |f| f.transports.contains(&t))
}
pub fn filter_by_format(
&self,
f: FormatPreference,
) -> impl Iterator<Item = &FeedDescriptor> {
self.manifest.feeds.iter().filter(move |feed| feed.formats.contains(&f))
}
pub fn search<'a>(
&'a self,
query: &'a str,
) -> impl Iterator<Item = &'a FeedDescriptor> + 'a {
let q = query.to_ascii_lowercase();
self.manifest.feeds.iter().filter(move |f| {
f.name.to_ascii_lowercase().contains(&q)
|| f.description
.as_ref()
.map(|d| d.to_ascii_lowercase().contains(&q))
.unwrap_or(false)
})
}
}
impl From<FeedManifest> for FeedCatalog {
fn from(m: FeedManifest) -> Self {
Self::new(m)
}
}