formatting and comments

This commit is contained in:
2026-07-16 00:12:26 -07:00
parent edb6d2b5b4
commit 994854d104
45 changed files with 2514 additions and 628 deletions
+35 -21
View File
@@ -1,3 +1,10 @@
//! Danmaku-overlay settings plus Bilibili gift and emoticon metadata caches.
//!
//! Settings are sanitized before persistence or projection. Catalog refreshes
//! replace the in-memory snapshot only after a complete valid response, so a
//! transient upstream failure preserves the last known gift images, prices and
//! emoticon URLs instead of breaking live rendering.
use std::{collections::HashMap, sync::Arc};
use serde::{Deserialize, Serialize};
@@ -123,16 +130,30 @@ pub struct EmoticonCatalog {
by_emoji: Arc<RwLock<HashMap<String, EmoticonMeta>>>,
}
// Parser return aliases keep the atomic cache-replacement contract visible:
// both lookup maps and their source count are produced before either lock is
// updated, so readers never observe a half-refreshed catalog.
type GiftCatalogSnapshot = (HashMap<i64, GiftMeta>, HashMap<String, GiftMeta>, usize);
type EmoticonCatalogSnapshot = (
HashMap<String, EmoticonMeta>,
HashMap<String, EmoticonMeta>,
usize,
);
impl EmoticonCatalog {
pub async fn len(&self) -> usize {
self.by_unique.read().await.len()
}
pub async fn is_empty(&self) -> bool {
self.len().await == 0
}
pub async fn get(&self, unique: Option<&str>, emoji: &str) -> Option<EmoticonMeta> {
if let Some(unique) = unique.filter(|value| !value.is_empty()) {
if let Some(emoticon) = self.by_unique.read().await.get(unique).cloned() {
return Some(emoticon);
}
if let Some(unique) = unique.filter(|value| !value.is_empty())
&& let Some(emoticon) = self.by_unique.read().await.get(unique).cloned()
{
return Some(emoticon);
}
self.by_emoji.read().await.get(emoji).cloned()
}
@@ -184,11 +205,15 @@ impl GiftCatalog {
self.by_id.read().await.len()
}
pub async fn is_empty(&self) -> bool {
self.len().await == 0
}
pub async fn get(&self, id: Option<i64>, name: &str) -> Option<GiftMeta> {
if let Some(id) = id {
if let Some(gift) = self.by_id.read().await.get(&id).cloned() {
return Some(gift);
}
if let Some(id) = id
&& let Some(gift) = self.by_id.read().await.get(&id).cloned()
{
return Some(gift);
}
self.by_name
.read()
@@ -231,9 +256,7 @@ impl GiftCatalog {
}
}
fn parse_catalog(
payload: &Value,
) -> Result<(HashMap<i64, GiftMeta>, HashMap<String, GiftMeta>, usize), String> {
fn parse_catalog(payload: &Value) -> Result<GiftCatalogSnapshot, String> {
let list = payload
.pointer("/data/gift_config/base_config/list")
.and_then(Value::as_array)
@@ -282,16 +305,7 @@ fn string_field(value: &Value, name: &str) -> Option<String> {
.map(ToOwned::to_owned)
}
fn parse_emoticon_catalog(
payload: &Value,
) -> Result<
(
HashMap<String, EmoticonMeta>,
HashMap<String, EmoticonMeta>,
usize,
),
String,
> {
fn parse_emoticon_catalog(payload: &Value) -> Result<EmoticonCatalogSnapshot, String> {
let packages = payload
.pointer("/data/data")
.and_then(Value::as_array)