Add errors to the writing functions.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Pedro de Oliveira 2023-04-30 07:39:55 +01:00
parent fd213f3836
commit 8a8ca0ba27
1 changed files with 173 additions and 146 deletions

View File

@ -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(),
}
}