WIP hacks to enable no_std and no alloc

This commit is contained in:
lif 2020-11-28 02:11:23 -08:00
parent 2f053855d5
commit 7b8f1095d4
8 changed files with 174 additions and 71 deletions

View File

@ -20,3 +20,10 @@ mp4parse = "0.8"
ogg = "0.5.1"
time = "0.1"
walkdir = "1.0"
[dependencies]
genio = { version = "0.2", optional = true, default-features = false }
heapless = { version = "0.5", optional = true, default-features = false }
[features]
nostd = ["genio", "heapless"]

View File

@ -5,7 +5,13 @@
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.
#[cfg(not(feature = "nostd"))]
use std::io;
#[cfg(feature = "nostd")]
use genio as io;
use crate::error::io_Result;
use input::ReadBytes;
// These tables were taken from the tables in crc.c in libflac.
@ -114,7 +120,7 @@ impl<R: ReadBytes> Crc16Reader<R> {
impl<R: ReadBytes> ReadBytes for Crc8Reader<R> {
#[inline(always)]
fn read_u8(&mut self) -> io::Result<u8> {
fn read_u8(&mut self) -> io_Result<u8> {
match self.inner.read_u8() {
Ok(byte) => {
self.update_state(byte);
@ -124,7 +130,7 @@ impl<R: ReadBytes> ReadBytes for Crc8Reader<R> {
}
}
fn read_u8_or_eof(&mut self) -> io::Result<Option<u8>> {
fn read_u8_or_eof(&mut self) -> io_Result<Option<u8>> {
match self.inner.read_u8_or_eof() {
Ok(Some(byte)) => {
self.update_state(byte);
@ -135,18 +141,18 @@ impl<R: ReadBytes> ReadBytes for Crc8Reader<R> {
}
}
fn read_into(&mut self, _buffer: &mut [u8]) -> io::Result<()> {
fn read_into(&mut self, _buffer: &mut [u8]) -> io_Result<()> {
panic!("CRC reader does not support read_into.");
}
fn skip(&mut self, _amount: u32) -> io::Result<()> {
fn skip(&mut self, _amount: u32) -> io_Result<()> {
panic!("CRC reader does not support skip, it does not compute CRC over skipped data.");
}
}
impl<R: ReadBytes> ReadBytes for Crc16Reader<R> {
#[inline(always)]
fn read_u8(&mut self) -> io::Result<u8> {
fn read_u8(&mut self) -> io_Result<u8> {
match self.inner.read_u8() {
Ok(byte) => {
self.update_state(byte);
@ -156,7 +162,7 @@ impl<R: ReadBytes> ReadBytes for Crc16Reader<R> {
}
}
fn read_u8_or_eof(&mut self) -> io::Result<Option<u8>> {
fn read_u8_or_eof(&mut self) -> io_Result<Option<u8>> {
match self.inner.read_u8_or_eof() {
Ok(Some(byte)) => {
self.update_state(byte);
@ -167,11 +173,11 @@ impl<R: ReadBytes> ReadBytes for Crc16Reader<R> {
}
}
fn read_into(&mut self, _buffer: &mut [u8]) -> io::Result<()> {
fn read_into(&mut self, _buffer: &mut [u8]) -> io_Result<()> {
panic!("CRC reader does not support read_into.");
}
fn skip(&mut self, _amount: u32) -> io::Result<()> {
fn skip(&mut self, _amount: u32) -> io_Result<()> {
panic!("CRC reader does not support skip, it does not compute CRC over skipped data.");
}
}

View File

@ -7,17 +7,26 @@
//! The `error` module defines the error and result types.
use std::error;
use std::fmt;
use std::io;
use std::result;
use std::string;
#[cfg(not(feature = "nostd"))]
use std::{error, io, string};
#[cfg(feature = "nostd")]
use genio as io;
use core::fmt;
use core::result;
#[cfg(not(feature = "nostd"))]
pub type io_Error = io::Error;
#[cfg(feature = "nostd")]
pub type io_Error = &'static str;
pub type io_Result<T> = core::result::Result<T, io_Error>;
/// An error that prevents successful decoding of the FLAC stream.
#[derive(Debug)]
pub enum Error {
/// Not a decoding error, but a problem with the underlying IO.
IoError(io::Error),
IoError(io_Error),
/// An ill-formed FLAC stream was encountered.
FormatError(&'static str),
@ -44,6 +53,7 @@ impl PartialEq for Error {
}
}
#[cfg(not(feature = "nostd"))]
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
match *self {
@ -61,6 +71,7 @@ impl fmt::Display for Error {
}
}
#[cfg(not(feature = "nostd"))]
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
@ -79,12 +90,13 @@ impl error::Error for Error {
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
impl From<io_Error> for Error {
fn from(err: io_Error) -> Error {
Error::IoError(err)
}
}
#[cfg(not(feature = "nostd"))]
impl From<string::FromUtf8Error> for Error {
fn from(_: string::FromUtf8Error) -> Error {
// Vendor strings and Vorbis comments are the only place where UTF-8 is
@ -92,6 +104,15 @@ impl From<string::FromUtf8Error> for Error {
Error::FormatError("Vorbis comment or vendor string is not valid UTF-8")
}
}
#[cfg(feature = "nostd")]
impl From<core::str::Utf8Error> for Error {
fn from(_: core::str::Utf8Error) -> Error {
// Vendor strings and Vorbis comments are the only place where UTF-8 is
// parsed into a String.
Error::FormatError("Vorbis comment or vendor string is not valid UTF-8")
}
}
/// A type for results generated by Claxon where the error type is hard-wired.
pub type Result<T> = result::Result<T, Error>;

View File

@ -7,8 +7,13 @@
//! The `frame` module deals with the frames that make up a FLAC stream.
#[cfg(not(feature = "nostd"))]
use std::i32;
#[cfg(feature = "nostd")]
type Vec<T> = heapless::Vec<T, heapless::consts::U256>; // TODO: wat size???
//use heapless::Vec;
use crc::{Crc8Reader, Crc16Reader};
use error::{Error, Result, fmt_err};
use input::{Bitstream, ReadBytes};
@ -416,7 +421,7 @@ impl Block {
first_sample_number: time,
block_size: bs,
channels: buffer.len() as u32 / bs,
buffer: buffer,
buffer,
}
}
@ -426,7 +431,7 @@ impl Block {
first_sample_number: 0,
block_size: 0,
channels: 0,
buffer: Vec::with_capacity(0),
buffer: Vec::new(),
}
}
@ -613,6 +618,7 @@ pub type FrameResult = Result<Option<Block>>;
/// be anything, it is assumed they will be overwritten anyway.
///
/// To use this function safely, the caller must overwrite all `new_len` bytes.
#[cfg(not(feature = "nostd"))]
fn ensure_buffer_len(mut buffer: Vec<i32>, new_len: usize) -> Vec<i32> {
if buffer.len() < new_len {
// Previous data will be overwritten, so instead of resizing the
@ -635,6 +641,15 @@ fn ensure_buffer_len(mut buffer: Vec<i32>, new_len: usize) -> Vec<i32> {
}
buffer
}
#[cfg(feature = "nostd")]
fn ensure_buffer_len(mut buffer: Vec<i32>, new_len: usize) -> Vec<i32> {
if buffer.len() < new_len {
buffer.resize(new_len, 0);
} else {
buffer.truncate(new_len);
}
buffer
}
#[test]
fn ensure_buffer_len_returns_buffer_with_new_len() {

View File

@ -12,8 +12,15 @@
//! checksumming of the data read. There is also a bitstream which is used
//! internally to read the bitstream.
use std::cmp;
use core::cmp;
#[cfg(not(feature = "nostd"))]
use std::io;
#[cfg(feature = "nostd")]
use genio as io;
#[cfg(feature = "nostd")]
use heapless::Vec;
use error::{io_Result, io_Error};
/// Similar to `std::io::BufRead`, but more performant.
///
@ -26,7 +33,10 @@ pub struct BufferedReader<R: io::Read> {
inner: R,
/// The buffer that holds data read from the inner reader.
buf: Box<[u8]>,
#[cfg(not(feature = "nostd"))]
buf: Vec<u8>,
#[cfg(feature = "nostd")]
buf: Vec<u8, heapless::consts::U256>,
/// The index of the first byte in the buffer which has not been consumed.
pos: u32,
@ -36,20 +46,22 @@ pub struct BufferedReader<R: io::Read> {
}
impl<R: io::Read> BufferedReader<R> {
/// Wrap the reader in a new buffered reader.
pub fn new(inner: R) -> BufferedReader<R> {
// Use a large-ish buffer size, such that system call overhead is
// negligible when replenishing the buffer. However, when fuzzing we
// want to have small samples, and still trigger the case where we have
// to replenish the buffer, so use a smaller buffer size there.
#[cfg(not(fuzzing))]
#[cfg(all(not(fuzzing), not(feature = "nostd")))]
const CAPACITY: usize = 2048;
#[cfg(all(not(fuzzing), feature = "nostd"))]
const CAPACITY: usize = 256;
#[cfg(fuzzing)]
const CAPACITY: usize = 31;
let buf = vec![0; CAPACITY].into_boxed_slice();
let buf = Vec::from_slice(&[0; CAPACITY]).unwrap();
BufferedReader {
inner: inner,
buf: buf,
@ -70,28 +82,28 @@ impl<R: io::Read> BufferedReader<R> {
/// Provides convenience methods to make input less cumbersome.
pub trait ReadBytes {
/// Reads a single byte, failing on EOF.
fn read_u8(&mut self) -> io::Result<u8>;
fn read_u8(&mut self) -> io_Result<u8>;
/// Reads a single byte, not failing on EOF.
fn read_u8_or_eof(&mut self) -> io::Result<Option<u8>>;
fn read_u8_or_eof(&mut self) -> io_Result<Option<u8>>;
/// Reads until the provided buffer is full.
fn read_into(&mut self, buffer: &mut [u8]) -> io::Result<()>;
fn read_into(&mut self, buffer: &mut [u8]) -> io_Result<()>;
/// Skips over the specified number of bytes.
///
/// For a buffered reader, this can help a lot by just bumping a pointer.
fn skip(&mut self, amount: u32) -> io::Result<()>;
fn skip(&mut self, amount: u32) -> io_Result<()>;
/// Reads two bytes and interprets them as a big-endian 16-bit unsigned integer.
fn read_be_u16(&mut self) -> io::Result<u16> {
fn read_be_u16(&mut self) -> io_Result<u16> {
let b0 = try!(self.read_u8()) as u16;
let b1 = try!(self.read_u8()) as u16;
Ok(b0 << 8 | b1)
}
/// Reads two bytes and interprets them as a big-endian 16-bit unsigned integer.
fn read_be_u16_or_eof(&mut self) -> io::Result<Option<u16>> {
fn read_be_u16_or_eof(&mut self) -> io_Result<Option<u16>> {
if let Some(b0) = try!(self.read_u8_or_eof()) {
if let Some(b1) = try!(self.read_u8_or_eof()) {
return Ok(Some((b0 as u16) << 8 | (b1 as u16)));
@ -101,7 +113,7 @@ pub trait ReadBytes {
}
/// Reads three bytes and interprets them as a big-endian 24-bit unsigned integer.
fn read_be_u24(&mut self) -> io::Result<u32> {
fn read_be_u24(&mut self) -> io_Result<u32> {
let b0 = try!(self.read_u8()) as u32;
let b1 = try!(self.read_u8()) as u32;
let b2 = try!(self.read_u8()) as u32;
@ -109,7 +121,7 @@ pub trait ReadBytes {
}
/// Reads four bytes and interprets them as a big-endian 32-bit unsigned integer.
fn read_be_u32(&mut self) -> io::Result<u32> {
fn read_be_u32(&mut self) -> io_Result<u32> {
let b0 = try!(self.read_u8()) as u32;
let b1 = try!(self.read_u8()) as u32;
let b2 = try!(self.read_u8()) as u32;
@ -118,7 +130,7 @@ pub trait ReadBytes {
}
/// Reads four bytes and interprets them as a little-endian 32-bit unsigned integer.
fn read_le_u32(&mut self) -> io::Result<u32> {
fn read_le_u32(&mut self) -> io_Result<u32> {
let b0 = try!(self.read_u8()) as u32;
let b1 = try!(self.read_u8()) as u32;
let b2 = try!(self.read_u8()) as u32;
@ -127,18 +139,20 @@ pub trait ReadBytes {
}
}
impl<R: io::Read> ReadBytes for BufferedReader<R>
{
impl<R: io::Read> ReadBytes for BufferedReader<R> {
#[inline(always)]
fn read_u8(&mut self) -> io::Result<u8> {
fn read_u8(&mut self) -> io_Result<u8> {
if self.pos == self.num_valid {
// The buffer was depleted, replenish it first.
self.pos = 0;
self.num_valid = try!(self.inner.read(&mut self.buf)) as u32;
self.num_valid = self.inner.read(&mut self.buf).map_err(|_| "read_u8")? as u32;
if self.num_valid == 0 {
#[cfg(not(feature = "nostd"))]
return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
"Expected one more byte."))
"Expected one more byte."));
#[cfg(feature = "nostd")]
return Err("Expected one more byte.");
}
}
@ -150,11 +164,11 @@ impl<R: io::Read> ReadBytes for BufferedReader<R>
Ok(byte)
}
fn read_u8_or_eof(&mut self) -> io::Result<Option<u8>> {
fn read_u8_or_eof(&mut self) -> io_Result<Option<u8>> {
if self.pos == self.num_valid {
// The buffer was depleted, try to replenish it first.
self.pos = 0;
self.num_valid = try!(self.inner.read(&mut self.buf)) as u32;
self.num_valid = self.inner.read(&mut self.buf).map_err(|_| "read_u8_or_eof")? as u32;
if self.num_valid == 0 {
return Ok(None);
@ -164,7 +178,7 @@ impl<R: io::Read> ReadBytes for BufferedReader<R>
Ok(Some(try!(self.read_u8())))
}
fn read_into(&mut self, buffer: &mut [u8]) -> io::Result<()> {
fn read_into(&mut self, buffer: &mut [u8]) -> io_Result<()> {
let mut bytes_left = buffer.len();
while bytes_left > 0 {
@ -178,10 +192,13 @@ impl<R: io::Read> ReadBytes for BufferedReader<R>
if bytes_left > 0 {
// Replenish the buffer if there is more to be read.
self.pos = 0;
self.num_valid = try!(self.inner.read(&mut self.buf)) as u32;
self.num_valid = self.inner.read(&mut self.buf).map_err(|_| "read_into")? as u32;
if self.num_valid == 0 {
#[cfg(not(feature = "nostd"))]
return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
"Expected more bytes."))
"Expected more bytes."));
#[cfg(feature = "nostd")]
return Err("Expected more bytes.");
}
}
}
@ -189,7 +206,7 @@ impl<R: io::Read> ReadBytes for BufferedReader<R>
Ok(())
}
fn skip(&mut self, mut amount: u32) -> io::Result<()> {
fn skip(&mut self, mut amount: u32) -> io_Result<()> {
while amount > 0 {
let num_left = self.num_valid - self.pos;
let read_now = cmp::min(amount, num_left);
@ -199,11 +216,14 @@ impl<R: io::Read> ReadBytes for BufferedReader<R>
if amount > 0 {
// If there is more to skip, refill the buffer first.
self.pos = 0;
self.num_valid = try!(self.inner.read(&mut self.buf)) as u32;
self.num_valid = self.inner.read(&mut self.buf).map_err(|_| "skip")? as u32;
if self.num_valid == 0 {
#[cfg(not(feature = "nostd"))]
return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
"Expected more bytes."))
"Expected more bytes."));
#[cfg(feature = "nostd")]
return Err("Expected more bytes.");
}
}
}
@ -214,36 +234,40 @@ impl<R: io::Read> ReadBytes for BufferedReader<R>
impl<'r, R: ReadBytes> ReadBytes for &'r mut R {
#[inline(always)]
fn read_u8(&mut self) -> io::Result<u8> {
fn read_u8(&mut self) -> io_Result<u8> {
(*self).read_u8()
}
fn read_u8_or_eof(&mut self) -> io::Result<Option<u8>> {
fn read_u8_or_eof(&mut self) -> io_Result<Option<u8>> {
(*self).read_u8_or_eof()
}
fn read_into(&mut self, buffer: &mut [u8]) -> io::Result<()> {
fn read_into(&mut self, buffer: &mut [u8]) -> io_Result<()> {
(*self).read_into(buffer)
}
fn skip(&mut self, amount: u32) -> io::Result<()> {
fn skip(&mut self, amount: u32) -> io_Result<()> {
(*self).skip(amount)
}
}
#[cfg(not(feature = "nostd"))]
impl<T: AsRef<[u8]>> ReadBytes for io::Cursor<T> {
fn read_u8(&mut self) -> io::Result<u8> {
fn read_u8(&mut self) -> io_Result<u8> {
let pos = self.position();
if pos < self.get_ref().as_ref().len() as u64 {
self.set_position(pos + 1);
Ok(self.get_ref().as_ref()[pos as usize])
} else {
Err(io::Error::new(io::ErrorKind::UnexpectedEof, "unexpected eof"))
#[cfg(not(feature = "nostd"))]
return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "unexpected eof"));
#[cfg(feature = "nostd")]
return Err("unexpected eof");
}
}
fn read_u8_or_eof(&mut self) -> io::Result<Option<u8>> {
fn read_u8_or_eof(&mut self) -> io_Result<Option<u8>> {
let pos = self.position();
if pos < self.get_ref().as_ref().len() as u64 {
self.set_position(pos + 1);
@ -253,7 +277,7 @@ impl<T: AsRef<[u8]>> ReadBytes for io::Cursor<T> {
}
}
fn read_into(&mut self, buffer: &mut [u8]) -> io::Result<()> {
fn read_into(&mut self, buffer: &mut [u8]) -> io_Result<()> {
let pos = self.position();
if pos + buffer.len() as u64 <= self.get_ref().as_ref().len() as u64 {
let start = pos as usize;
@ -262,17 +286,23 @@ impl<T: AsRef<[u8]>> ReadBytes for io::Cursor<T> {
self.set_position(pos + buffer.len() as u64);
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::UnexpectedEof, "unexpected eof"))
#[cfg(not(feature = "nostd"))]
return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "unexpected eof"));
#[cfg(feature = "nostd")]
return Err("unexpected eof");
}
}
fn skip(&mut self, amount: u32) -> io::Result<()> {
fn skip(&mut self, amount: u32) -> io_Result<()> {
let pos = self.position();
if pos + amount as u64 <= self.get_ref().as_ref().len() as u64 {
self.set_position(pos + amount as u64);
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::UnexpectedEof, "unexpected eof"))
#[cfg(not(feature = "nostd"))]
return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "unexpected eof"));
#[cfg(feature = "nostd")]
return Err("unexpected eof");
}
}
}
@ -444,7 +474,7 @@ impl<R: ReadBytes> Bitstream<R> {
/// Reading a single bit can be done more efficiently than reading
/// more than one bit, because a bit never straddles a byte boundary.
#[inline(always)]
pub fn read_bit(&mut self) -> io::Result<bool> {
pub fn read_bit(&mut self) -> io_Result<bool> {
// If no bits are left, we will need to read the next byte.
let result = if self.bits_left == 0 {
@ -472,7 +502,7 @@ impl<R: ReadBytes> Bitstream<R> {
/// Because the reader buffers a byte internally, reading unary can be done
/// more efficiently than by just reading bit by bit.
#[inline(always)]
pub fn read_unary(&mut self) -> io::Result<u32> {
pub fn read_unary(&mut self) -> io_Result<u32> {
// Start initially with the number of zeros that are in the buffer byte
// already (counting from the most significant bit).
let mut n = self.data.leading_zeros();
@ -512,7 +542,7 @@ impl<R: ReadBytes> Bitstream<R> {
/// Reads at most eight bits.
#[inline(always)]
pub fn read_leq_u8(&mut self, bits: u32) -> io::Result<u8> {
pub fn read_leq_u8(&mut self, bits: u32) -> io_Result<u8> {
// Of course we can read no more than 8 bits, but we do not want the
// performance overhead of the assertion, so only do it in debug mode.
debug_assert!(bits <= 8);
@ -559,7 +589,7 @@ impl<R: ReadBytes> Bitstream<R> {
/// Read n bits, where 8 < n <= 16.
#[inline(always)]
pub fn read_gt_u8_leq_u16(&mut self, bits: u32) -> io::Result<u32> {
pub fn read_gt_u8_leq_u16(&mut self, bits: u32) -> io_Result<u32> {
debug_assert!((8 < bits) && (bits <= 16));
// The most significant bits of the current byte are valid. Shift them
@ -603,7 +633,7 @@ impl<R: ReadBytes> Bitstream<R> {
/// Reads at most 16 bits.
#[inline(always)]
pub fn read_leq_u16(&mut self, bits: u32) -> io::Result<u16> {
pub fn read_leq_u16(&mut self, bits: u32) -> io_Result<u16> {
// As with read_leq_u8, this only makes sense if we read <= 16 bits.
debug_assert!(bits <= 16);
@ -623,7 +653,7 @@ impl<R: ReadBytes> Bitstream<R> {
/// Reads at most 32 bits.
#[inline(always)]
pub fn read_leq_u32(&mut self, bits: u32) -> io::Result<u32> {
pub fn read_leq_u32(&mut self, bits: u32) -> io_Result<u32> {
// As with read_leq_u8, this only makes sense if we read <= 32 bits.
debug_assert!(bits <= 32);

View File

@ -68,10 +68,16 @@
#![warn(missing_docs)]
use std::fs;
use std::io;
use std::mem;
use std::path;
#![cfg_attr(feature = "nostd", no_std)]
#[cfg(not(feature = "nostd"))]
pub use std::{fs, io, path};
#[cfg(feature = "nostd")] extern crate genio;
#[cfg(feature = "nostd")] extern crate heapless;
#[cfg(feature = "nostd")] use genio as io;
use core::mem;
use error::fmt_err;
use frame::FrameReader;
use input::{BufferedReader, ReadBytes};
@ -419,6 +425,7 @@ impl<R: io::Read> FlacReader<R> {
}
}
#[cfg(not(feature = "nostd"))]
impl FlacReader<fs::File> {
/// Attempts to create a reader that reads from the specified file.
///

View File

@ -9,8 +9,13 @@
use error::{Error, Result, fmt_err};
use input::ReadBytes;
use std::str;
use std::slice;
use core::str;
use core::slice;
#[cfg(feature = "nostd")]
type String = heapless::String<heapless::consts::U256>;
#[cfg(feature = "nostd")]
type Vec<T> = heapless::Vec<T, heapless::consts::U256>; // TODO: wat sizes
#[derive(Clone, Copy)]
struct MetadataBlockHeader {
@ -195,7 +200,7 @@ impl<'a> Iterator for GetTag<'a> {
fn next(&mut self) -> Option<&'a str> {
// This import is actually required on Rust 1.13.
#[allow(unused_imports)]
use std::ascii::AsciiExt;
//use std::ascii::AsciiExt;
while self.index < self.vorbis_comments.len() {
let (ref comment, sep_idx) = self.vorbis_comments[self.index];
@ -429,6 +434,9 @@ fn read_vorbis_comment_block<R: ReadBytes>(input: &mut R, length: u32) -> Result
// 32-bit vendor string length, and comment count.
let vendor_len = try!(input.read_le_u32());
if vendor_len > length - 8 { return fmt_err("vendor string too long") }
#[cfg(feature = "nostd")]
let mut vendor_bytes = Vec::new();
#[cfg(not(feature = "nostd"))]
let mut vendor_bytes = Vec::with_capacity(vendor_len as usize);
// We can safely set the lenght of the vector here; the uninitialized memory
@ -446,6 +454,9 @@ fn read_vorbis_comment_block<R: ReadBytes>(input: &mut R, length: u32) -> Result
if comments_len >= length / 4 {
return fmt_err("too many entries for Vorbis comment block")
}
#[cfg(feature = "nostd")]
let mut comments = Vec::new();
#[cfg(not(feature = "nostd"))]
let mut comments = Vec::with_capacity(comments_len as usize);
let mut bytes_left = length - 8 - vendor_len;
@ -470,6 +481,9 @@ fn read_vorbis_comment_block<R: ReadBytes>(input: &mut R, length: u32) -> Result
}
// For the same reason as above, setting the length is safe here.
#[cfg(feature = "nostd")]
let mut comment_bytes = Vec::new();
#[cfg(not(feature = "nostd"))]
let mut comment_bytes = Vec::with_capacity(comment_len as usize);
unsafe { comment_bytes.set_len(comment_len as usize); }
try!(input.read_into(&mut comment_bytes));
@ -541,6 +555,9 @@ fn read_application_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<(u
// uninitialized memory is never exposed: read_into will either fill the
// buffer completely, or return an err, in which case the memory is not
// exposed.
#[cfg(feature = "nostd")]
let mut data = Vec::new();
#[cfg(not(feature = "nostd"))]
let mut data = Vec::with_capacity(length as usize - 4);
unsafe { data.set_len(length as usize - 4); }
try!(input.read_into(&mut data));

View File

@ -7,8 +7,8 @@
//! The `subframe` module deals with subframes that make up a frame of the FLAC stream.
use std::cmp;
use std::num;
use core::cmp;
use core::num;
use error::{Error, Result, fmt_err};
use input::{Bitstream, ReadBytes};