Skip to content

Migration 0.4

ChouChiu edited this page Sep 23, 2026 · 1 revision

从 0.3 升级到 0.4

0.4.0 是一次以「去重复、去过度防御」为主的整理,只带来三处破坏性改动,多数项目只需要删掉几行代码。另外修复了一个让 KRC 解密完全不可用的 bug。

依赖写法

六个 crate 统一为 0.4.0。因为升的是 minor 位,写作 "0.3" 的依赖不会被自动升上来,需要显式改:

[dependencies]
lyrics-helper = "0.4"

仅需离线解析时禁用默认 feature:

[dependencies]
lyrics-helper = { version = "0.4", default-features = false }

FullSyllableInfo 不再缓存聚合值

FullSyllableInfo 过去用 RefCell/Cell 缓存拼接文本与首尾时间,改完子音节必须调用 refresh_properties() 让缓存失效。但 sub_items 是公开字段,任何直接赋值都会绕过这个约定,缓存本身就是个坑。0.4.0 改为每次由 sub_items 即时推导。

Important

FullSyllableInfo::refresh_properties() 已删除。原先的调用点直接删掉这一行即可,不需要任何替代写法。

use lyrics_helper::{FullSyllableInfo, SyllableInfo, SyllableItem};

let mut item = SyllableItem::from(FullSyllableInfo::new(vec![
    SyllableInfo::new("Hel".to_string(), 0, 500),
    SyllableInfo::new("lo".to_string(), 500, 1000),
]));

if let Some(full) = item.as_full_mut() {
    full.sub_items_mut()[0].text = "新文本".to_string();
    // 0.3 及以前:这里还需要 full.refresh_properties();
}

assert_eq!(item.text(), "新文本lo");

text() 一直是返回新分配的 String,去掉缓存后开销没有变化。

副作用:歌词模型变为 Sync

去掉内部可变性之后,FullSyllableInfo、SyllableItem、LineInfo、LyricsData 全部满足 Send + Sync,可以直接跨线程共享:

fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<lyrics_helper::LyricsData>();

LRCLIB 的两个响应结构合并

SearchResultItem 与 GetLyricResult 字段完全相同,已合并为 LyricItem。两个旧名称保留为类型别名,现有代码不需要改动。

use lyrics_helper::providers::web::lrclib::response::{GetLyricResult, LyricItem, SearchResultItem};

// 三个名字指向同一个类型
let _: fn(LyricItem) = |_| {};
let _: fn(SearchResultItem) = |_| {};
let _: fn(GetLyricResult) = |_| {};

汽水音乐移除两个公开项

Important

providers::web::soda_music::api::get_detail 与 providers::web::soda_music::api::USER_AGENT 已删除。

get_detail 的返回类型 TrackDetailResponse 字段全是 pub(crate),外部拿到也读不出任何内容;取歌词请用 get_lyrics,它直接返回 (原文, 翻译):

use lyrics_helper::providers::web::soda_music;

#[tokio::main]
async fn main() {
    match soda_music::api::get_lyrics("7013585879398584100").await {
        Ok((original, translation)) => println!("{original:?} / {translation:?}"),
        Err(error) => println!("获取失败: {error}"),
    }
}

USER_AGENT 是一个没有任何调用方的常量,搜索接口与 H5 接口各自使用自己的 UA。

KRC 解密修复(行为变化)

0.3 及以前,KRC 解压后无条件丢掉首字节。真实的 KRC 正文带 UTF-8 BOM(EF BB BF),丢掉首字节后剩下的 BB BF 使整段不是合法 UTF-8,于是 decrypt_krc() 一路返回 None——KRC 解密实际上完全不可用。

0.4.0 改为只在确实匹配到 BOM 时去掉这 3 个字节:

  • 正文带 BOM:现在能正常解出歌词(此前返回 None);
  • 正文不带 BOM:首字符不再被吃掉(此前 [ti:...] 会变成 ti:...]);
  • KrcDecrypter::decrypt_bytes 不再把半截 BOM 泄漏给调用方。

细节与上游差异见歌词解密。

其他

以下改动不影响公开 API,但值得知道:

  • TTML 解析修复:曲目时长的候选键(durationMs / durationInMillis / duration / length)此前只要第一个取不到值就整体放弃,现在会逐个尝试。
  • 搜索查询串(build_search_string / build_refinement_queries)现在会把元数据缺字段时留下的连续空格折叠成一个。
  • 仓库根目录那份与 lyrics-helper/examples/ 重复的 examples/ 已删除;示例始终位于 lyrics-helper/examples/。

Clone this wiki locally