-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Atom soundness and usability fixes (#100)
Mark atom-reading methods as unsafe. Renamed Space into AlignedSpace, and made it a Dynamically Sized Type. Removed all of the use_padding parameters in atom writing methods. Added a SpaceReader struct. Removed all the odd split_* methods on Space. Added VecSpace, replacing SpaceList. Renamed FramedMutSpace into AtomSpaceWriter Renamed RootMutSpace into SpaceCursor. Renamed the MutSpace trait into SpaceWriter. Added the Terminated struct. Made UnidentifiedAtom a Dynamically Sized Type. Added the AtomHeader struct. Removed lifetimes from the Atom types (and removed many extra lifetimes accordingly). Removed ReadParameter and WriteParameter associated types. Moved all base atom types to a sub-module. Removed lifetimes in the Atom type. Removed Vector type parameter. Moved Sequence unit type reading into a type parameter for its reader. Added an AtomError error type, as well as sub-error types AtomReadError, AtomWriteError, and AlignmentError. Added a special prelude for the atom-implementing side. Added lots of extra documentation, especially in AlignedSpace.
- Loading branch information
Showing
64 changed files
with
4,995 additions
and
2,646 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
pub mod chunk; | ||
pub mod object; | ||
pub mod scalar; | ||
pub mod sequence; | ||
pub mod string; | ||
pub mod tuple; | ||
pub mod vector; | ||
|
||
use urid::*; | ||
|
||
/// An URID collection of all standard atom types, provided for convenience. | ||
#[derive(Clone)] | ||
pub struct AtomURIDCollection { | ||
pub blank: URID<object::Blank>, | ||
pub double: URID<scalar::Double>, | ||
pub float: URID<scalar::Float>, | ||
pub int: URID<scalar::Int>, | ||
pub long: URID<scalar::Long>, | ||
pub urid: URID<scalar::AtomURID>, | ||
pub bool: URID<scalar::Bool>, | ||
pub vector: URID<vector::Vector>, | ||
pub chunk: URID<chunk::Chunk>, | ||
pub literal: URID<string::Literal>, | ||
pub object: URID<object::Object>, | ||
pub property: URID<object::Property>, | ||
pub string: URID<string::String>, | ||
pub tuple: URID<tuple::Tuple>, | ||
pub sequence: URID<sequence::Sequence>, | ||
} | ||
|
||
impl URIDCollection for AtomURIDCollection { | ||
fn from_map<M: Map + ?Sized>(map: &M) -> Option<Self> { | ||
Some(Self { | ||
blank: map.map_type()?, | ||
double: map.map_type()?, | ||
float: map.map_type()?, | ||
int: map.map_type()?, | ||
long: map.map_type()?, | ||
urid: map.map_type()?, | ||
bool: map.map_type()?, | ||
vector: map.map_type()?, | ||
chunk: map.map_type()?, | ||
literal: map.map_type()?, | ||
object: map.map_type()?, | ||
property: map.map_type()?, | ||
string: map.map_type()?, | ||
tuple: map.map_type()?, | ||
sequence: map.map_type()?, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
//! An atom containing memory of undefined type. | ||
//! | ||
//! This contents of this atom is considered as a simple blob of data. It used, for example, by the host to transmit the size of a writable atom port. Since it is so simple, it does not need a reading or writing parameter. | ||
//! | ||
//! # Example | ||
//! ``` | ||
//! use lv2_core::prelude::*; | ||
//! use lv2_atom::prelude::*; | ||
//! | ||
//! use lv2_atom::space::{AtomSpace, AtomWriter, SpaceWriter}; | ||
//! | ||
//! #[derive(PortCollection)] | ||
//! struct MyPorts { | ||
//! input: InputPort<AtomPort>, | ||
//! output: OutputPort<AtomPort>, | ||
//! } | ||
//! | ||
//! fn run(ports: &mut MyPorts, urids: &AtomURIDCollection) { | ||
//! let in_chunk: &AtomSpace = ports.input.read(urids.chunk).unwrap(); | ||
//! let mut out_chunk: AtomWriter = ports.output.write(urids.chunk).unwrap(); | ||
//! | ||
//! let bytes = in_chunk.as_bytes(); | ||
//! out_chunk.write_bytes(bytes).unwrap(); | ||
//! } | ||
//! ``` | ||
//! | ||
//! # Specification | ||
//! | ||
//! [http://lv2plug.in/ns/ext/atom/atom.html#Chunk](http://lv2plug.in/ns/ext/atom/atom.html#Chunk) | ||
use crate::space::error::{AtomReadError, AtomWriteError}; | ||
use crate::space::*; | ||
use crate::AtomWriter; | ||
use crate::{Atom, AtomHandle}; | ||
use urid::UriBound; | ||
|
||
/// An atom containing an arbitrary byte buffer. | ||
/// | ||
/// [See also the module documentation.](index.html) | ||
pub struct Chunk; | ||
|
||
unsafe impl UriBound for Chunk { | ||
const URI: &'static [u8] = sys::LV2_ATOM__Chunk; | ||
} | ||
|
||
pub struct ChunkReaderHandle; | ||
impl<'a> AtomHandle<'a> for ChunkReaderHandle { | ||
type Handle = &'a AtomSpace; | ||
} | ||
|
||
pub struct ChunkWriterHandle; | ||
impl<'a> AtomHandle<'a> for ChunkWriterHandle { | ||
type Handle = AtomWriter<'a>; | ||
} | ||
|
||
impl Atom for Chunk { | ||
type ReadHandle = ChunkReaderHandle; | ||
type WriteHandle = ChunkWriterHandle; | ||
|
||
#[inline] | ||
unsafe fn read( | ||
body: &AtomSpace, | ||
) -> Result<<Self::ReadHandle as AtomHandle>::Handle, AtomReadError> { | ||
Ok(body) | ||
} | ||
|
||
#[inline] | ||
fn write( | ||
frame: AtomWriter, | ||
) -> Result<<Self::WriteHandle as AtomHandle>::Handle, AtomWriteError> { | ||
Ok(frame) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::atoms::chunk::*; | ||
use crate::*; | ||
|
||
#[test] | ||
fn test_chunk_and_slice_writer() { | ||
const SLICE_LENGTH: usize = 42; | ||
|
||
let map = HashURIDMapper::new(); | ||
let urids = crate::atoms::AtomURIDCollection::from_map(&map).unwrap(); | ||
|
||
let mut raw_space = AlignedVec::<AtomHeader>::new_with_capacity(64); | ||
let raw_space = raw_space.as_space_mut(); | ||
|
||
// writing | ||
{ | ||
let mut space = SpaceCursor::new(raw_space.as_bytes_mut()); | ||
let mut writer = space.write_atom(urids.chunk).unwrap(); | ||
let data = writer.allocate(SLICE_LENGTH).unwrap(); | ||
|
||
for (i, value) in data.iter_mut().enumerate() { | ||
*value = i as u8; | ||
} | ||
|
||
space.write_value(41u8).unwrap(); | ||
} | ||
|
||
// verifying | ||
{ | ||
let atom = unsafe { raw_space.read().next_atom() }.unwrap(); | ||
assert_eq!(atom.header().size_of_body(), SLICE_LENGTH); | ||
assert_eq!(atom.header().urid(), urids.chunk.get()); | ||
|
||
let data = atom.body().as_bytes(); | ||
for (i, value) in data.iter().enumerate() { | ||
assert_eq!(*value as usize, i); | ||
} | ||
} | ||
|
||
// reading | ||
{ | ||
let data = | ||
unsafe { Chunk::read(raw_space.read().next_atom().unwrap().body()) }.unwrap(); | ||
assert_eq!(data.bytes_len(), SLICE_LENGTH); | ||
|
||
for (i, value) in data.as_bytes().iter().enumerate() { | ||
assert_eq!(*value as usize, i); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.