1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::error::{LoftyError, Result};
use crate::ogg::constants::VORBIS_SETUP_HEAD;
use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use byteorder::{LittleEndian, ReadBytesExt};
use ogg_pager::Page;
pub(crate) fn write_to(
data: &mut File,
writer: &mut Vec<u8>,
first_md_content: Vec<u8>,
ser: u32,
pages: &mut [Page],
) -> Result<()> {
let mut remaining = Vec::new();
let reached_md_end: bool;
let mut c = Cursor::new(first_md_content);
c.seek(SeekFrom::Start(7))?;
let vendor_len = c.read_u32::<LittleEndian>()?;
c.seek(SeekFrom::Current(i64::from(vendor_len)))?;
let total_comments = c.read_u32::<LittleEndian>()?;
let comments_pos = c.seek(SeekFrom::Current(0))?;
c.seek(SeekFrom::End(0))?;
loop {
let p = Page::read(data, false)?;
if p.header_type != 1 {
data.seek(SeekFrom::Start(p.start as u64))?;
data.read_to_end(&mut remaining)?;
reached_md_end = true;
break;
}
c.write_all(&p.content)?;
}
if !reached_md_end {
return Err(LoftyError::Vorbis("File ends with comment header"));
}
c.seek(SeekFrom::Start(comments_pos))?;
for _ in 0..total_comments {
let len = c.read_u32::<LittleEndian>()?;
c.seek(SeekFrom::Current(i64::from(len)))?;
}
if c.read_u8()? != 1 {
return Err(LoftyError::Vorbis("File is missing a framing bit"));
}
let mut header_ident = [0; 7];
c.read_exact(&mut header_ident)?;
if header_ident != VORBIS_SETUP_HEAD {
return Err(LoftyError::Vorbis("File is missing setup header"));
}
c.seek(SeekFrom::Current(-7))?;
let mut setup = Vec::new();
c.read_to_end(&mut setup)?;
let pages_len = pages.len() - 1;
for (i, mut p) in pages.iter_mut().enumerate() {
p.serial = ser;
if i == pages_len {
p.content.push(1);
let mut seg_table = Vec::new();
seg_table.extend(p.segments().iter());
seg_table.extend(ogg_pager::segments(&*setup));
let mut seg_table_len = seg_table.len();
if seg_table_len > 255 {
seg_table = seg_table.split_at(255).0.to_vec();
seg_table_len = 255;
}
seg_table.insert(0, seg_table_len as u8);
let page = p.extend(&*setup);
let mut p_bytes = p.as_bytes();
let seg_count = p_bytes[26] as usize;
p_bytes.splice(26..27 + seg_count, seg_table);
p_bytes.splice(22..26, ogg_pager::crc32(&*p_bytes).to_le_bytes().to_vec());
writer.write_all(&*p_bytes)?;
if let Some(mut page) = page {
page.serial = ser;
page.gen_crc();
writer.write_all(&*page.as_bytes())?;
}
break;
}
p.gen_crc();
writer.write_all(&*p.as_bytes())?;
}
writer.write_all(&*remaining)?;
Ok(())
}