formatting and comments
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user