use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SourceKind {
GithubRepo,
HnStory,
Crate,
HfModel,
}
impl SourceKind {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
SourceKind::GithubRepo => "github_repo",
SourceKind::HnStory => "hn_story",
SourceKind::Crate => "crate",
SourceKind::HfModel => "hf_model",
}
}
#[must_use]
pub const fn tag(self) -> &'static str {
match self {
SourceKind::GithubRepo => "GH",
SourceKind::HnStory => "HN",
SourceKind::Crate => "CR",
SourceKind::HfModel => "HF",
}
}
#[must_use]
pub fn parse(s: &str) -> Option<SourceKind> {
match s {
"github_repo" => Some(SourceKind::GithubRepo),
"hn_story" => Some(SourceKind::HnStory),
"crate" => Some(SourceKind::Crate),
"hf_model" => Some(SourceKind::HfModel),
_ => None,
}
}
}
impl fmt::Display for SourceKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SubjectRecord {
pub kind: SourceKind,
pub key: String,
pub title: Option<String>,
pub lang: Option<String>,
pub url: Option<String>,
pub topics: Vec<String>,
pub created_at: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Observation {
pub ts: i64,
pub score: i64,
pub extra1: i64,
pub extra2: i64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RepoListed {
pub full_name: String,
pub language: Option<String>,
pub topics: Vec<String>,
pub description: Option<String>,
pub is_fork: bool,
pub pushed_at: Option<String>,
pub stars: i64,
}
#[derive(Debug, Clone, PartialEq)]
pub struct VelocityRow {
pub kind: SourceKind,
pub key: String,
pub title: Option<String>,
pub lang: Option<String>,
pub url: Option<String>,
pub topics: Vec<String>,
pub score_now: i64,
pub score_prev: i64,
pub window_secs: i64,
pub velocity_per_day: f64,
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use super::*;
#[test]
fn source_kind_roundtrips() {
for kind in [
SourceKind::GithubRepo,
SourceKind::HnStory,
SourceKind::Crate,
] {
assert_eq!(SourceKind::parse(kind.as_str()), Some(kind));
}
assert_eq!(SourceKind::parse("nope"), None);
}
#[test]
fn tags_are_distinct() {
let tags = [
SourceKind::GithubRepo.tag(),
SourceKind::HnStory.tag(),
SourceKind::Crate.tag(),
];
assert_eq!(tags.len(), 3);
assert_ne!(tags[0], tags[1]);
assert_ne!(tags[1], tags[2]);
}
}