vfmt: весь код в формате V master (без изменений логики)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
K1ndWha1eandClaude Opus 5.5 committed 2026-10-11 17:31:02 +03:00
1 parent 4c9184aeb2
commit 6161a7faaa
12 files changed
+405 -287

No files matched your search

+1 -1
View File
@@ -26,4 +26,4 @@ pub enum EnumID3v23 as u8 {
apic
txxx
unknown
}
}
+43 -39
View File
@@ -4,23 +4,23 @@ import encoding.iconv
@[heap]
pub struct Frame {
pub mut:
data string
mut:
prev_size u64
cur_size u64
start u64
end u64
encoding_name string
name string
encoding_name_idx u8
addition []u8
encoded_data []u8
apic ?[]u8
encoded_size []u8
modified bool
// Фрейм целиком в том виде, в каком он был прочитан из файла
raw []u8
pub mut:
data string
mut:
prev_size u64
cur_size u64
start u64
end u64
encoding_name string
name string
encoding_name_idx u8
addition []u8
encoded_data []u8
apic ?[]u8
encoded_size []u8
modified bool
// Фрейм целиком в том виде, в каком он был прочитан из файла
raw []u8
}
// Во фрейме первый байт указывает кодировку 0 - ISO-8859-1 (Latin-1), 1 - UTF-16LE
@@ -32,10 +32,10 @@ fn (mut frame Frame) fill(bytes []u8, start_position u64, idv3_version u8) {
frame.name = bytes[frame.start..frame.start + 4].bytestr()
// Размер фрейма
frame.cur_size = if idv3_version == 3 {
get_size_v23(bytes[frame.start + 4..frame.start + 8])
} else {
get_size_v24(bytes[frame.start + 4..frame.start + 8])
frame.cur_size = if idv3_version == 3 {
get_size_v23(bytes[frame.start + 4..frame.start + 8])
} else {
get_size_v24(bytes[frame.start + 4..frame.start + 8])
}
// Конец фрейма
frame.end = frame.start + frame.cur_size + 10
@@ -44,16 +44,16 @@ fn (mut frame Frame) fill(bytes []u8, start_position u64, idv3_version u8) {
frame.modified = false
// Содержимое фрейма
frame.encoding_name = match bytes[frame.start + 10] {
0 { "ISO-8859-1" }
1 { "UTF-16LE" }
2 { "UTF-16BE" }
else { "UTF-8" }
frame.encoding_name = match bytes[frame.start + 10] {
0 { 'ISO-8859-1' }
1 { 'UTF-16LE' }
2 { 'UTF-16BE' }
else { 'UTF-8' }
}
frame.encoding_name_idx = u8(bytes[frame.start + 10])
if frame.name.to_lower() == "apic" {
if frame.name.to_lower() == 'apic' {
// Дополнительные байты с информацией (MIME)
frame.addition = bytes[frame.start + 10..frame.start + 24]
// Фрейм целиком вместе с заголовком, чтобы записать его обратно без изменений
@@ -65,13 +65,13 @@ fn (mut frame Frame) fill(bytes []u8, start_position u64, idv3_version u8) {
// UTF-16 с BOM (01): 2 байта маркера, по ним определяется порядок байт
if frame.encoding_name_idx == 1 && data_start + 2 <= frame.end {
if bytes[data_start] == 0xFE && bytes[data_start + 1] == 0xFF {
frame.encoding_name = "UTF-16BE"
frame.encoding_name = 'UTF-16BE'
}
data_start += 2
}
// Замыкающие нули не относятся к данным
frame.data = (iconv.encoding_to_vstring(bytes[data_start..frame.end], frame.encoding_name) or { "" }).all_before('\x00')
frame.data = (iconv.encoding_to_vstring(bytes[data_start..frame.end], frame.encoding_name) or { '' }).all_before('\x00')
frame.addition = bytes[frame.start..frame.start + 10]
}
@@ -86,10 +86,10 @@ pub fn (mut frame Frame) init(tag_name string, idv3_version u8) {
fn (mut frame Frame) set_unicode_encoding(idv3_version u8) {
// В v2.3 нет UTF-8, там Юникод только UTF-16 с BOM
if idv3_version == 3 {
frame.encoding_name = "UTF-16LE"
frame.encoding_name = 'UTF-16LE'
frame.encoding_name_idx = 1
} else {
frame.encoding_name = "UTF-8"
frame.encoding_name = 'UTF-8'
frame.encoding_name_idx = 3
}
}
@@ -97,10 +97,10 @@ fn (mut frame Frame) set_unicode_encoding(idv3_version u8) {
// Кодируем длину фрейма с нужным сдвигом
@[inline]
pub fn (mut frame Frame) encode_size(idv3_version u8) {
stride := if idv3_version == 3 {
[u64(24), u64(16), u64(8), u64(0xFF)]
} else {
[u64(21), u64(14), u64(7), u64(0x7F)]
stride := if idv3_version == 3 {
[u64(24), u64(16), u64(8), u64(0xFF)]
} else {
[u64(21), u64(14), u64(7), u64(0x7F)]
}
mut encoded_size := []u8{len: 4}
@@ -123,13 +123,17 @@ pub fn (mut frame Frame) encode_frame(idv3_version u8) {
// Не удалось закодировать в исходной кодировке фрейма, переходим на Юникод
frame.set_unicode_encoding(idv3_version)
iconv.vstring_to_encoding(frame.data, frame.encoding_name) or {
panic("не удалось закодировать фрейм ${frame.name}: ${err}")
panic('не удалось закодировать фрейм ${frame.name}: ${err}')
}
}
// Для UTF-16 с BOM (01) перед текстом нужен маркер порядка байт
frame.encoded_data = if frame.encoding_name_idx == 1 {
mut bom := if frame.encoding_name == "UTF-16BE" { [u8(0xFE), 0xFF] } else { [u8(0xFF), 0xFE] }
mut bom := if frame.encoding_name == 'UTF-16BE' {
[u8(0xFE), 0xFF]
} else {
[u8(0xFF), 0xFE]
}
bom << encoded_data
bom
} else {
@@ -174,7 +178,7 @@ pub fn (mut frame Frame) get_encoded_frame_tag(idv3_version u8) []u8 {
pub fn (mut frame Frame) to_bytes(idv3_version u8) []u8 {
// Картинка и нетронутые фреймы пишутся как были прочитаны,
// чтобы не потерять то, что не разбирается (язык в COMM, значение в TXXX, бинарные фреймы)
if frame.raw.len > 0 && (!frame.modified || frame.name == "APIC") {
if frame.raw.len > 0 && (!frame.modified || frame.name == 'APIC') {
return frame.raw
}
@@ -195,4 +199,4 @@ pub fn (mut frame Frame) set_data(data string) {
frame.data = data
frame.modified = true
}
}
+154 -32
View File
@@ -151,47 +151,169 @@ enum Genre as u8 {
anime = 145
jpop = 146
synthpop = 147
unknown = 255
unknown = 255
}
const genres_name = [
'Blues', 'Classic Rock', 'Country', 'Dance', 'Disco', 'Funk', 'Grunge',
'Hip-Hop', 'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop', 'R&B',
'Rap', 'Reggae', 'Rock', 'Techno', 'Industrial', 'Alternative', 'Ska',
'Death Metal', 'Pranks', 'Soundtrack', 'Euro-Techno', 'Ambient',
'Trip-Hop', 'Vocal', 'Jazz+Funk', 'Fusion', 'Trance', 'Classical',
'Instrumental', 'Acid', 'House', 'Game', 'Sound Clip', 'Gospel',
'Noise', 'AlternRock', 'Bass', 'Soul', 'Punk', 'Space', 'Meditative',
'Instrumental Pop', 'Instrumental Rock', 'Ethnic', 'Gothic', 'Darkwave',
'Techno-Industrial', 'Electronic', 'Pop-Folk', 'Eurodance', 'Dream',
'Southern Rock', 'Comedy', 'Cult', 'Gangsta', 'Top 40', 'Christian Rap',
'Pop/Funk', 'Jungle', 'Native American', 'Cabaret', 'New Wave',
'Psychadelic', 'Rave', 'Showtunes', 'Trailer', 'Lo-Fi', 'Tribal',
'Acid Punk', 'Acid Jazz', 'Polka', 'Retro', 'Musical', 'Rock & Roll',
'Blues',
'Classic Rock',
'Country',
'Dance',
'Disco',
'Funk',
'Grunge',
'Hip-Hop',
'Jazz',
'Metal',
'New Age',
'Oldies',
'Other',
'Pop',
'R&B',
'Rap',
'Reggae',
'Rock',
'Techno',
'Industrial',
'Alternative',
'Ska',
'Death Metal',
'Pranks',
'Soundtrack',
'Euro-Techno',
'Ambient',
'Trip-Hop',
'Vocal',
'Jazz+Funk',
'Fusion',
'Trance',
'Classical',
'Instrumental',
'Acid',
'House',
'Game',
'Sound Clip',
'Gospel',
'Noise',
'AlternRock',
'Bass',
'Soul',
'Punk',
'Space',
'Meditative',
'Instrumental Pop',
'Instrumental Rock',
'Ethnic',
'Gothic',
'Darkwave',
'Techno-Industrial',
'Electronic',
'Pop-Folk',
'Eurodance',
'Dream',
'Southern Rock',
'Comedy',
'Cult',
'Gangsta',
'Top 40',
'Christian Rap',
'Pop/Funk',
'Jungle',
'Native American',
'Cabaret',
'New Wave',
'Psychadelic',
'Rave',
'Showtunes',
'Trailer',
'Lo-Fi',
'Tribal',
'Acid Punk',
'Acid Jazz',
'Polka',
'Retro',
'Musical',
'Rock & Roll',
'Hard Rock',
// Winamp
'Folk', 'Folk-Rock', 'National Folk', 'Swing', 'Fast Fusion', 'Bebob',
'Latin', 'Revival', 'Celtic', 'Bluegrass', 'Avantgarde', 'Gothic Rock',
'Progressive Rock', 'Psychedelic Rock', 'Symphonic Rock', 'Slow Rock',
'Big Band', 'Chorus', 'Easy Listening', 'Acoustic', 'Humour', 'Speech',
'Chanson', 'Opera', 'Chamber Music', 'Sonata', 'Symphony', 'Booty Bass',
'Primus', 'Porn Groove', 'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba',
'Folklore', 'Ballad', 'Power Ballad', 'Rhythmic Soul', 'Freestyle', 'Duet',
'Punk Ballad', 'Drum Solo', 'A Cappella', 'Euro-House', 'Dance Hall',
'Goa', 'Drum & Bass', 'Club-House', 'Hardcore', 'Terror', 'Indie',
'BritPop', 'Negerpunk', 'Polsk Punk', 'Beat', 'Christian Gangsta',
'Heavy Metal', 'Black Metal', 'Crossover', 'Contemporary Christian',
'Christian Rock', 'Merengue', 'Salsa', 'Thrash Metal', 'Anime', 'JPop',
'Synthpop'
'Folk',
'Folk-Rock',
'National Folk',
'Swing',
'Fast Fusion',
'Bebob',
'Latin',
'Revival',
'Celtic',
'Bluegrass',
'Avantgarde',
'Gothic Rock',
'Progressive Rock',
'Psychedelic Rock',
'Symphonic Rock',
'Slow Rock',
'Big Band',
'Chorus',
'Easy Listening',
'Acoustic',
'Humour',
'Speech',
'Chanson',
'Opera',
'Chamber Music',
'Sonata',
'Symphony',
'Booty Bass',
'Primus',
'Porn Groove',
'Satire',
'Slow Jam',
'Club',
'Tango',
'Samba',
'Folklore',
'Ballad',
'Power Ballad',
'Rhythmic Soul',
'Freestyle',
'Duet',
'Punk Ballad',
'Drum Solo',
'A Cappella',
'Euro-House',
'Dance Hall',
'Goa',
'Drum & Bass',
'Club-House',
'Hardcore',
'Terror',
'Indie',
'BritPop',
'Negerpunk',
'Polsk Punk',
'Beat',
'Christian Gangsta',
'Heavy Metal',
'Black Metal',
'Crossover',
'Contemporary Christian',
'Christian Rock',
'Merengue',
'Salsa',
'Thrash Metal',
'Anime',
'JPop',
'Synthpop',
]
pub fn (genre Genre) str() string{
pub fn (genre Genre) str() string {
match genre {
.unknown {
return "Unknown"
} else {
return 'Unknown'
}
else {
return genres_name[u8(genre)]
}
}
}
}
+17 -17
View File
@@ -4,28 +4,28 @@ import os { File }
import encoding.iconv
import utils
// Определить кодировку utf-8 или cp-1251
@[inline]
fn decode_bytes(bytes []u8) string {
format := if utils.is_utf8(bytes) { "UTF-8" } else { "CP1251" }
format := if utils.is_utf8(bytes) { 'UTF-8' } else { 'CP1251' }
text := (iconv.encoding_to_vstring(bytes, format) or { "Can't decode" }).all_before('\x00')
return text
return text
}
// Извлечение метаданных из ID3 v1
pub fn (mut tag ID3v1) get_metadata(last_bytes []u8) {
tag.title = decode_bytes(last_bytes[3..33])
tag.artist = decode_bytes(last_bytes[33..63])
tag.album = decode_bytes(last_bytes[63..92])
tag.year = decode_bytes(last_bytes[93..97])
tag.comment = decode_bytes(last_bytes[97..125])
tag.track = if last_bytes[125] == u8(0) {last_bytes[126].str()} else { "" }
tag.track = if last_bytes[125] == u8(0) { last_bytes[126].str() } else { '' }
genre := Genre.from(last_bytes[127..128][0]) or { Genre.unknown }
tag.genre = genre.str()}
tag.genre = genre.str()
}
// Конвертировать ID3 v2.3 в ID3 v1
pub fn (id3v1 ID3v1) to_v23() ID3v23 {
@@ -60,7 +60,7 @@ fn cut_or_trim(data string, capacity i8) []u8 {
mut final_data := []u8{len: capacity, init: 0}
if data.len > 0 {
bytes_data := iconv.vstring_to_encoding(data, "CP1251") or { []u8{len: capacity} }
bytes_data := iconv.vstring_to_encoding(data, 'CP1251') or { []u8{len: capacity} }
diff := capacity - bytes_data.len
if diff > 0 {
@@ -79,7 +79,7 @@ fn cut_or_trim(data string, capacity i8) []u8 {
pub fn (mut id3v1 ID3v1) to_bytes() []u8 {
mut bytes := []u8{cap: 128}
bytes << "TAG".bytes()
bytes << 'TAG'.bytes()
bytes << cut_or_trim(id3v1.title, i8(30))
bytes << cut_or_trim(id3v1.artist, i8(30))
bytes << cut_or_trim(id3v1.album, i8(30))
@@ -87,7 +87,7 @@ pub fn (mut id3v1 ID3v1) to_bytes() []u8 {
bytes << cut_or_trim(id3v1.comment, i8(28))
// bytes << cut_or_trim(id3v1.track, i8(2))
bytes << if id3v1.track.len != 0 { [u8(0), id3v1.track.u8()]} else { [u8(1), u8(0)] }
bytes << if id3v1.track.len != 0 { [u8(0), id3v1.track.u8()] } else { [u8(1), u8(0)] }
id_genre := Genre.from(id3v1.genre.to_lower()) or { Genre.unknown }
bytes << u8(id_genre) // cut_or_trim([u8(id_genre)], i8(2))
@@ -100,15 +100,15 @@ pub fn (mut id3v1 ID3v1) to_bytes() []u8 {
// Добавление изменённого тэга
pub fn (mut id3v1 ID3v1) insert(mut audio File, position i8) []u8 {
// if !id3v1.embedded {
bytes_tag := id3v1.to_bytes()
// Уcтановка указателя на последний байт
audio.seek(0, os.SeekMode.end) or { panic(err) }
// Положение указателя
size := audio.tell() or { panic(err) }
// Чтение всех байта, кроме последних 128
mut all_bytes := audio.read_bytes(int(size))#[..position].clone()
bytes_tag := id3v1.to_bytes()
// Уcтановка указателя на последний байт
audio.seek(0, os.SeekMode.end) or { panic(err) }
// Положение указателя
size := audio.tell() or { panic(err) }
// Чтение всех байта, кроме последних 128
mut all_bytes := audio.read_bytes(int(size))#[..position].clone()
all_bytes << bytes_tag
all_bytes << bytes_tag
// }
return all_bytes
+6 -8
View File
@@ -27,7 +27,6 @@ import os { File }
const start_idx = 10
pub fn (mut tag ID3v23) add_frame(frame Frame) {
name := EnumID3v23.from(frame.name.to_lower()) or { EnumID3v23.unknown }
@@ -84,7 +83,6 @@ pub fn (mut id3v23 ID3v23) encode_embed_tags() {
encode_embed_tags[ID3v23](mut id3v23)
}
// Заполнение тэга
pub fn (mut id3v23 ID3v23) fill_tags(mut audio File) {
dump_data[ID3v23](mut id3v23, mut audio)
@@ -93,12 +91,12 @@ pub fn (mut id3v23 ID3v23) fill_tags(mut audio File) {
// Конвертировать ID3 v2.3 в ID3 v1
pub fn (id3v23 ID3v23) to_v1() ID3v1 {
return ID3v1{
genre: id3v23.tcon.data
title: id3v23.tit2.data
artist: id3v23.tpe2.data
album: id3v23.talb.data
track: id3v23.trck.data.split("/")[0]
year: id3v23.tyer.data
genre: id3v23.tcon.data
title: id3v23.tit2.data
artist: id3v23.tpe2.data
album: id3v23.talb.data
track: id3v23.trck.data.split('/')[0]
year: id3v23.tyer.data
comment: id3v23.txxx.data
}
}
-3
View File
@@ -2,7 +2,6 @@ module metadata
import os { File }
pub fn (mut tag ID3v24) add_frame(frame Frame) {
name := EnumID3v24.from(frame.name.to_lower()) or { EnumID3v24.unknown }
@@ -43,7 +42,6 @@ pub fn (mut tag ID3v24) add_frame(frame Frame) {
}
}
@[inline]
fn get_size_v24(size_bytes []u8) u64 {
return (u64(size_bytes[0]) << 21) | (u64(size_bytes[1]) << 14) | (u64(size_bytes[2]) << 7) | u64(size_bytes[3])
@@ -77,7 +75,6 @@ pub fn (id3v24 ID3v24) to_v1() ID3v1 {
}
}
// Добавление аудио после нового тэга
pub fn (mut id3v24 ID3v24) insert_tags_into_audio(mut audio File) ! {
insert_tags_into_audio[ID3v24](mut id3v24, mut audio)!
+90 -93
View File
@@ -1,109 +1,106 @@
module metadata
@[heap; minify]
pub struct ID3v1 {
pub mut:
// Жанр
genre string
// Название аудиодорожки
title string
// Актёр озучания
artist string
// Название альбома
album string
// Записывается как 2/5, что значит 2 трэк из 5
track string
// Год записи, может int нужно
year string
// Комментарий
comment string
// Присутвует ли тэг
embedded bool
pub mut:
// Жанр
genre string
// Название аудиодорожки
title string
// Актёр озучания
artist string
// Название альбома
album string
// Записывается как 2/5, что значит 2 трэк из 5
track string
// Год записи, может int нужно
year string
// Комментарий
comment string
// Присутвует ли тэг
embedded bool
}
@[heap; minify]
pub struct ID3v23 {
pub mut:
// Размер тэга
size u64
// Название аудиодорожки
tit2 Frame
// Автор
tpe1 Frame
// Исполнитель
tpe2 Frame
// Название альбома
talb Frame
// Год выпуска
tyer Frame
// Номер трека
trck Frame
// Жанр
tcon Frame
// Композитор (автор)
tcop Frame
// Обложка
apic Frame
// Комментарий
txxx Frame
// Затычка
unknown Frame
// Остальные фреймы
others []Frame
encoded_header []u8
// Присутвует ли тэг
embedded bool
// Версия тэга
version u8 = 3
title string = "ID3"
pub mut:
// Размер тэга
size u64
// Название аудиодорожки
tit2 Frame
// Автор
tpe1 Frame
// Исполнитель
tpe2 Frame
// Название альбома
talb Frame
// Год выпуска
tyer Frame
// Номер трека
trck Frame
// Жанр
tcon Frame
// Композитор (автор)
tcop Frame
// Обложка
apic Frame
// Комментарий
txxx Frame
// Затычка
unknown Frame
// Остальные фреймы
others []Frame
encoded_header []u8
// Присутвует ли тэг
embedded bool
// Версия тэга
version u8 = 3
title string = 'ID3'
}
@[heap; minify]
pub struct ID3v24 {
pub mut:
// Размер тэга
size u64
// Название аудиодорожки
tit2 Frame
// Автор
tpe1 Frame
// Исполнитель
tpe2 Frame
// Название альбома
talb Frame
// Год выпуска
tdrc Frame
// Номер трека
trck Frame
// Жанр
tcon Frame
// Композитор (автор)
tcop Frame
// Обложка
apic Frame
// Комментарий
txxx Frame
// Затычка
modified_frames []Frame
// Остальные фреймы
others []Frame
// Версия тэга
version u8 = 4
// Присутвует ли тэг
embedded bool
// Закодированный хэдер
encoded_header []u8
title string = "ID3"
pub mut:
// Размер тэга
size u64
// Название аудиодорожки
tit2 Frame
// Автор
tpe1 Frame
// Исполнитель
tpe2 Frame
// Название альбома
talb Frame
// Год выпуска
tdrc Frame
// Номер трека
trck Frame
// Жанр
tcon Frame
// Композитор (автор)
tcop Frame
// Обложка
apic Frame
// Комментарий
txxx Frame
// Затычка
modified_frames []Frame
// Остальные фреймы
others []Frame
// Версия тэга
version u8 = 4
// Присутвует ли тэг
embedded bool
// Закодированный хэдер
encoded_header []u8
title string = 'ID3'
}
pub struct Audio {
pub mut:
id3v1 ID3v1
id3v23 ID3v23
id3v24 ID3v24
path string
extension string = ".mp3"
pub mut:
id3v1 ID3v1
id3v23 ID3v23
id3v24 ID3v24
path string
extension string = '.mp3'
}
+9 -10
View File
@@ -2,12 +2,11 @@ module metadata
import os
pub fn (mut audio Audio) detect_tags(mut data os.File) {
// ? --- Проверка версии ID3v1 ---
last_bytes := get_bytes(mut data, -128, 3)
if last_bytes[0..3].bytestr() == "TAG" {
if last_bytes[0..3].bytestr() == 'TAG' {
audio.id3v1.embedded = true
}
// ===============================
@@ -15,7 +14,7 @@ pub fn (mut audio Audio) detect_tags(mut data os.File) {
// ? --- Проверка версии ID3v23.3 ---
first_ten_bytes := get_bytes(mut data, 0, 4)
if first_ten_bytes[..3].bytestr() == "ID3" {
if first_ten_bytes[..3].bytestr() == 'ID3' {
if first_ten_bytes[3] == 3 {
audio.id3v23.embedded = true
} else if first_ten_bytes[3] == 4 {
@@ -38,7 +37,7 @@ pub fn get_bytes(mut audio os.File, position int, size int) []u8 {
last_bytes := audio.read_bytes_at(size, u64(pos))
audio.seek(0, os.SeekMode.start) or { panic(err) }
// =========================================================
return last_bytes
}
@@ -92,7 +91,7 @@ pub fn encode_header[T](mut id3v T) {
id3v.encoded_header << [id3v.version]
// Минорная версия и спец. флаги
id3v.encoded_header << []u8{len: 2}
id3v.encoded_header << metadata.encode_header_size(id3v.size)
}
@@ -110,7 +109,7 @@ pub fn encode_embed_tags[T](mut id3v2 T) {
// Читаются только заполненные тэги
if id3v2.$(field.name).cur_size > 0 {
// Фрейма не было в файле и init не вызывался: имя берётся из поля структуры
if id3v2.$(field.name).name == "" && field.name.len == 4 {
if id3v2.$(field.name).name == '' && field.name.len == 4 {
id3v2.$(field.name).init(field.name, id3v2.version)
}
@@ -140,8 +139,8 @@ pub fn encode_embed_tags[T](mut id3v2 T) {
// Добавляет аудио из файла после нового тэга в encoded_header, старый тэг пропускается
pub fn insert_tags_into_audio[T](mut id3v2 T, mut audio os.File) ! {
header := get_bytes(mut audio, 0, 10)
if header.len < 10 || header[..3].bytestr() != "ID3" {
return error("в файле нет тэга ID3v2")
if header.len < 10 || header[..3].bytestr() != 'ID3' {
return error('в файле нет тэга ID3v2')
}
// Размер старого тэга берётся из файла, id3v2.size уже хранит размер нового.
@@ -155,7 +154,7 @@ pub fn insert_tags_into_audio[T](mut id3v2 T, mut audio os.File) ! {
audio.seek(0, .end)!
file_size := u64(audio.tell()!)
if audio_start > file_size {
return error("размер тэга (${audio_start}) больше размера файла (${file_size})")
return error('размер тэга (${audio_start}) больше размера файла (${file_size})')
}
// Аудио читается сразу в конец encoded_header, без промежуточной копии всего файла
@@ -168,7 +167,7 @@ pub fn insert_tags_into_audio[T](mut id3v2 T, mut audio os.File) ! {
for read < sound_len {
n := unsafe { audio.read_into_ptr(&u8(id3v2.encoded_header.data) + header_len + read, sound_len - read)! }
if n == 0 {
return error("файл закончился раньше ожидаемого")
return error('файл закончился раньше ожидаемого')
}
read += n
}