Add errors to the writing functions.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
fd213f3836
commit
8a8ca0ba27
319
src/writer.rs
319
src/writer.rs
|
@ -1,182 +1,209 @@
|
|||
use crate::types::{BlockType, Codec, Voc, SIGNATURE1, SIGNATURE2};
|
||||
use std::io::{Error, ErrorKind};
|
||||
|
||||
fn get_size(size: usize) -> [u8; 3] {
|
||||
let size = (size as u32).to_le_bytes();
|
||||
[size[0], size[1], size[2]]
|
||||
}
|
||||
|
||||
fn write_terminator() -> Vec<u8> {
|
||||
vec![0]
|
||||
}
|
||||
|
||||
fn write_sound_data(block: &BlockType) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
bytes.extend_from_slice(&[1]);
|
||||
if let BlockType::SoundData {
|
||||
sample_rate,
|
||||
codec,
|
||||
data,
|
||||
} = block
|
||||
{
|
||||
let header_size = 2;
|
||||
bytes.extend_from_slice(&get_size(data.len() + header_size));
|
||||
let frequency_divisor: u8 = (256_u32 - 1000000_u32 / sample_rate) as u8;
|
||||
bytes.extend_from_slice(&[frequency_divisor]);
|
||||
let codec_id: u8 = match codec {
|
||||
Codec::Pcm8BitUnsigned => 0,
|
||||
Codec::Adpcm4to8 => 1,
|
||||
Codec::Adpcm3to8 => 2,
|
||||
Codec::Adpcm2to8 => 3,
|
||||
Codec::Pcm16BitSigned => 4,
|
||||
Codec::Alaw => 5,
|
||||
Codec::Ulaw => 6,
|
||||
_ => panic!("Invalid codec"),
|
||||
};
|
||||
bytes.extend_from_slice(&[codec_id]);
|
||||
bytes.extend_from_slice(data);
|
||||
fn write_terminator(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let bytes = vec![0];
|
||||
match block {
|
||||
BlockType::Terminator => Ok(bytes),
|
||||
_ => Err(Error::new(ErrorKind::Other, "Block is not Terminator")),
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
fn write_sound_data_continuation(block: &BlockType) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
bytes.extend_from_slice(&[2]);
|
||||
if let BlockType::SoundDataContinuation { data } = block {
|
||||
bytes.extend_from_slice(&get_size(data.len()));
|
||||
bytes.extend_from_slice(data);
|
||||
fn write_sound_data(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let mut bytes = vec![1];
|
||||
match block {
|
||||
BlockType::SoundData {
|
||||
sample_rate,
|
||||
codec,
|
||||
data,
|
||||
} => {
|
||||
let header_size = 2;
|
||||
bytes.extend_from_slice(&get_size(data.len() + header_size));
|
||||
let frequency_divisor: u8 = (256_u32 - 1000000_u32 / sample_rate) as u8;
|
||||
bytes.extend_from_slice(&[frequency_divisor]);
|
||||
let codec_id: u8 = match codec {
|
||||
Codec::Pcm8BitUnsigned => 0,
|
||||
Codec::Adpcm4to8 => 1,
|
||||
Codec::Adpcm3to8 => 2,
|
||||
Codec::Adpcm2to8 => 3,
|
||||
Codec::Pcm16BitSigned => 4,
|
||||
Codec::Alaw => 5,
|
||||
Codec::Ulaw => 6,
|
||||
_ => panic!("Invalid codec"),
|
||||
};
|
||||
bytes.extend_from_slice(&[codec_id]);
|
||||
bytes.extend_from_slice(data);
|
||||
Ok(bytes)
|
||||
}
|
||||
_ => Err(Error::new(ErrorKind::Other, "Block is not SoundData")),
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
fn write_silence(block: &BlockType) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
bytes.extend_from_slice(&[3]);
|
||||
if let BlockType::Silence {
|
||||
length,
|
||||
sample_rate,
|
||||
} = block
|
||||
{
|
||||
let header_size = 3;
|
||||
bytes.extend_from_slice(&get_size(header_size));
|
||||
bytes.extend_from_slice(&(length + 1).to_le_bytes());
|
||||
let frequency_divisor: u8 = (256_u32 - 1000000_u32 / sample_rate) as u8;
|
||||
bytes.extend_from_slice(&[frequency_divisor]);
|
||||
fn write_sound_data_continuation(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let mut bytes = vec![2];
|
||||
match block {
|
||||
BlockType::SoundDataContinuation { data } => {
|
||||
bytes.extend_from_slice(&get_size(data.len()));
|
||||
bytes.extend_from_slice(data);
|
||||
Ok(bytes)
|
||||
}
|
||||
_ => Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"Block is not SoundDataContinuation",
|
||||
)),
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
fn write_marker(block: &BlockType) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
bytes.extend_from_slice(&[4]);
|
||||
if let BlockType::Marker { value } = block {
|
||||
let header_size = 2;
|
||||
bytes.extend_from_slice(&get_size(header_size));
|
||||
bytes.extend_from_slice(&value.to_le_bytes());
|
||||
fn write_silence(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let mut bytes = vec![3];
|
||||
match block {
|
||||
BlockType::Silence {
|
||||
length,
|
||||
sample_rate,
|
||||
} => {
|
||||
let header_size = 3;
|
||||
bytes.extend_from_slice(&get_size(header_size));
|
||||
bytes.extend_from_slice(&(length + 1).to_le_bytes());
|
||||
let frequency_divisor: u8 = (256_u32 - 1000000_u32 / sample_rate) as u8;
|
||||
bytes.extend_from_slice(&[frequency_divisor]);
|
||||
Ok(bytes)
|
||||
}
|
||||
_ => Err(Error::new(ErrorKind::Other, "Block is not Silence")),
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
fn write_text(block: &BlockType) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
bytes.extend_from_slice(&[5]);
|
||||
if let BlockType::Text { data } = block {
|
||||
bytes.extend_from_slice(&get_size(data.len()));
|
||||
bytes.extend_from_slice(data);
|
||||
fn write_marker(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let mut bytes = vec![4];
|
||||
match block {
|
||||
BlockType::Marker { value } => {
|
||||
let header_size = 2;
|
||||
bytes.extend_from_slice(&get_size(header_size));
|
||||
bytes.extend_from_slice(&value.to_le_bytes());
|
||||
Ok(bytes)
|
||||
}
|
||||
_ => Err(Error::new(ErrorKind::Other, "Block is not Marker")),
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
fn write_repeat_start(block: &BlockType) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
bytes.extend_from_slice(&[6]);
|
||||
if let BlockType::RepeatStart { count } = block {
|
||||
let header_size = 2;
|
||||
bytes.extend_from_slice(&get_size(header_size));
|
||||
bytes.extend_from_slice(&count.to_le_bytes());
|
||||
fn write_text(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let mut bytes = vec![5];
|
||||
match block {
|
||||
BlockType::Text { data } => {
|
||||
bytes.extend_from_slice(&get_size(data.len()));
|
||||
bytes.extend_from_slice(data);
|
||||
Ok(bytes)
|
||||
}
|
||||
_ => Err(Error::new(ErrorKind::Other, "Block is not Text")),
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
fn write_repeat_end() -> Vec<u8> {
|
||||
vec![7]
|
||||
}
|
||||
|
||||
fn write_extra_information(block: &BlockType) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
bytes.extend_from_slice(&[8]);
|
||||
if let BlockType::ExtraInformation {
|
||||
sample_rate,
|
||||
codec,
|
||||
channels,
|
||||
} = block
|
||||
{
|
||||
let header_size = 4;
|
||||
bytes.extend_from_slice(&get_size(header_size));
|
||||
let frequency_divisor =
|
||||
(65536 - (256000000_u32 / ((*channels as u32 + 1) * sample_rate))) as u16;
|
||||
bytes.extend_from_slice(&frequency_divisor.to_le_bytes());
|
||||
let codec_id: u8 = match codec {
|
||||
Codec::Pcm8BitUnsigned => 0,
|
||||
Codec::Adpcm4to8 => 1,
|
||||
Codec::Adpcm3to8 => 2,
|
||||
Codec::Adpcm2to8 => 3,
|
||||
Codec::Pcm16BitSigned => 4,
|
||||
Codec::Alaw => 5,
|
||||
Codec::Ulaw => 6,
|
||||
_ => panic!("Invalid codec"),
|
||||
};
|
||||
bytes.extend_from_slice(&[codec_id]);
|
||||
bytes.extend_from_slice(&[*channels]);
|
||||
fn write_repeat_start(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let mut bytes = vec![6];
|
||||
match block {
|
||||
BlockType::RepeatStart { count } => {
|
||||
let header_size = 2;
|
||||
bytes.extend_from_slice(&get_size(header_size));
|
||||
bytes.extend_from_slice(&count.to_le_bytes());
|
||||
Ok(bytes)
|
||||
}
|
||||
_ => Err(Error::new(ErrorKind::Other, "Block is not RepeatStart")),
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
fn write_sound_data_new(block: &BlockType) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
bytes.extend_from_slice(&[9]);
|
||||
if let BlockType::SoundDataNew {
|
||||
sample_rate,
|
||||
bits,
|
||||
channels,
|
||||
codec,
|
||||
reserved,
|
||||
data,
|
||||
} = block
|
||||
{
|
||||
let header_size = 12;
|
||||
bytes.extend_from_slice(&get_size(data.len() + header_size));
|
||||
bytes.extend_from_slice(&sample_rate.to_le_bytes());
|
||||
bytes.extend_from_slice(&[*bits]);
|
||||
bytes.extend_from_slice(&[*channels]);
|
||||
let codec_id: u16 = match codec {
|
||||
Codec::Pcm8BitUnsigned => 0,
|
||||
Codec::Adpcm4to8 => 1,
|
||||
Codec::Adpcm3to8 => 2,
|
||||
Codec::Adpcm2to8 => 3,
|
||||
Codec::Pcm16BitSigned => 4,
|
||||
Codec::Alaw => 5,
|
||||
Codec::Ulaw => 6,
|
||||
Codec::Adpcm4to16 => 0x0200,
|
||||
};
|
||||
bytes.extend_from_slice(&codec_id.to_le_bytes());
|
||||
bytes.extend_from_slice(&reserved.to_le_bytes());
|
||||
bytes.extend_from_slice(data);
|
||||
fn write_repeat_end(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let bytes = vec![7];
|
||||
match block {
|
||||
BlockType::RepeatEnd => Ok(bytes),
|
||||
_ => Err(Error::new(ErrorKind::Other, "Block is not RepeatEnd")),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_extra_information(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let mut bytes = vec![8];
|
||||
match block {
|
||||
BlockType::ExtraInformation {
|
||||
sample_rate,
|
||||
codec,
|
||||
channels,
|
||||
} => {
|
||||
let header_size = 4;
|
||||
bytes.extend_from_slice(&get_size(header_size));
|
||||
let frequency_divisor =
|
||||
(65536 - (256000000_u32 / ((*channels as u32 + 1) * sample_rate))) as u16;
|
||||
bytes.extend_from_slice(&frequency_divisor.to_le_bytes());
|
||||
let codec_id: u8 = match codec {
|
||||
Codec::Pcm8BitUnsigned => 0,
|
||||
Codec::Adpcm4to8 => 1,
|
||||
Codec::Adpcm3to8 => 2,
|
||||
Codec::Adpcm2to8 => 3,
|
||||
Codec::Pcm16BitSigned => 4,
|
||||
Codec::Alaw => 5,
|
||||
Codec::Ulaw => 6,
|
||||
_ => panic!("Invalid codec"),
|
||||
};
|
||||
bytes.extend_from_slice(&[codec_id]);
|
||||
bytes.extend_from_slice(&[*channels]);
|
||||
Ok(bytes)
|
||||
}
|
||||
_ => Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"Block is not ExtraInformation",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_sound_data_new(block: &BlockType) -> Result<Vec<u8>, Error> {
|
||||
let mut bytes = vec![9];
|
||||
match block {
|
||||
BlockType::SoundDataNew {
|
||||
sample_rate,
|
||||
bits,
|
||||
channels,
|
||||
codec,
|
||||
reserved,
|
||||
data,
|
||||
} => {
|
||||
let header_size = 12;
|
||||
bytes.extend_from_slice(&get_size(data.len() + header_size));
|
||||
bytes.extend_from_slice(&sample_rate.to_le_bytes());
|
||||
bytes.extend_from_slice(&[*bits]);
|
||||
bytes.extend_from_slice(&[*channels]);
|
||||
let codec_id: u16 = match codec {
|
||||
Codec::Pcm8BitUnsigned => 0,
|
||||
Codec::Adpcm4to8 => 1,
|
||||
Codec::Adpcm3to8 => 2,
|
||||
Codec::Adpcm2to8 => 3,
|
||||
Codec::Pcm16BitSigned => 4,
|
||||
Codec::Alaw => 5,
|
||||
Codec::Ulaw => 6,
|
||||
Codec::Adpcm4to16 => 0x0200,
|
||||
};
|
||||
bytes.extend_from_slice(&codec_id.to_le_bytes());
|
||||
bytes.extend_from_slice(&reserved.to_le_bytes());
|
||||
bytes.extend_from_slice(data);
|
||||
Ok(bytes)
|
||||
}
|
||||
_ => Err(Error::new(ErrorKind::Other, "Block is not SoundDataNew")),
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
fn write_block(block: &BlockType) -> Vec<u8> {
|
||||
match block {
|
||||
BlockType::Terminator => write_terminator(),
|
||||
BlockType::SoundData { .. } => write_sound_data(block),
|
||||
BlockType::SoundDataContinuation { .. } => write_sound_data_continuation(block),
|
||||
BlockType::Silence { .. } => write_silence(block),
|
||||
BlockType::Marker { .. } => write_marker(block),
|
||||
BlockType::Text { .. } => write_text(block),
|
||||
BlockType::RepeatStart { .. } => write_repeat_start(block),
|
||||
BlockType::RepeatEnd => write_repeat_end(),
|
||||
BlockType::ExtraInformation { .. } => write_extra_information(block),
|
||||
BlockType::SoundDataNew { .. } => write_sound_data_new(block),
|
||||
BlockType::Terminator => write_terminator(block).unwrap(),
|
||||
BlockType::SoundData { .. } => write_sound_data(block).unwrap(),
|
||||
BlockType::SoundDataContinuation { .. } => write_sound_data_continuation(block).unwrap(),
|
||||
BlockType::Silence { .. } => write_silence(block).unwrap(),
|
||||
BlockType::Marker { .. } => write_marker(block).unwrap(),
|
||||
BlockType::Text { .. } => write_text(block).unwrap(),
|
||||
BlockType::RepeatStart { .. } => write_repeat_start(block).unwrap(),
|
||||
BlockType::RepeatEnd => write_repeat_end(block).unwrap(),
|
||||
BlockType::ExtraInformation { .. } => write_extra_information(block).unwrap(),
|
||||
BlockType::SoundDataNew { .. } => write_sound_data_new(block).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue