Skip to content

Commit

Permalink
More WIP, still not working
Browse files Browse the repository at this point in the history
  • Loading branch information
prokopyl committed Sep 9, 2021
1 parent efbd941 commit 4a80d43
Show file tree
Hide file tree
Showing 16 changed files with 216 additions and 131 deletions.
2 changes: 1 addition & 1 deletion atom/src/atoms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub struct AtomURIDCollection {
}

impl AtomURIDCollection {
pub fn vector<S: scalar::ScalarAtom>(&self) -> URID<vector::Vector<S>> {
pub fn vector<'a, 'b: 'a, S: scalar::ScalarAtom<'a, 'b>>(&self) -> URID<vector::Vector<S>> {
unsafe { URID::new_unchecked(self.vector.get()) }
}
}
4 changes: 2 additions & 2 deletions atom/src/atoms/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,11 @@ mod tests {

let (header, atom) = properties[0];
assert_eq!(header.key, first_key);
assert_eq!(atom.read(urids.int, ()).unwrap(), first_value);
assert_eq!(*atom.read(urids.int, ()).unwrap(), first_value);

let (header, atom) = properties[1];
assert_eq!(header.key, second_key);
assert_eq!(atom.read(urids.float, ()).unwrap(), second_value);
assert_eq!(*atom.read(urids.float, ()).unwrap(), second_value);
}
}
}
88 changes: 52 additions & 36 deletions atom/src/atoms/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//! /// Something like a plugin's run method.
//! fn run(ports: &mut MyPorts, urids: &AtomURIDCollection) {
//! // Scalar atoms don't need a reading parameter.
//! let read_value: f32 = ports.input.read(urids.float, ()).unwrap();
//! let read_value: &f32 = ports.input.read(urids.float, ()).unwrap();
//!
//! // Writing is done with the value of the atom.
//! ports.output.init(urids.float, 17.0).unwrap();
Expand All @@ -37,7 +37,16 @@ use urid::URID;
/// An atom that only contains a single, scalar value.
///
/// Since scalar values are so simple, the reading and writing methods are exactly the same.
pub trait ScalarAtom: UriBound {
pub trait ScalarAtom<'handle, 'space: 'handle>:
Atom<
'handle,
'space,
ReadParameter = (),
ReadHandle = &'handle Self::InternalType,
WriteParameter = Self::InternalType,
WriteHandle = (),
> + UriBound
{
/// The internal representation of the atom.
///
/// For example, the `Int` atom has the internal type of `i32`, which is `i32` on most platforms.
Expand All @@ -47,15 +56,15 @@ pub trait ScalarAtom: UriBound {
///
/// If the space does not contain the atom or is not big enough, return `None`. The second return value is the space behind the atom.
#[inline]
unsafe fn read_scalar(body: &AtomSpace) -> Option<Self::InternalType> {
body.read().next_value().copied()
unsafe fn read_scalar(body: &AtomSpace) -> Option<&Self::InternalType> {
body.read().next_value()
}

/// Try to write the atom into a space.
///
/// Write an atom with the value of `value` into the space and return a mutable reference to the written value. If the space is not big enough, return `None`.
#[inline]
fn write_scalar<'handle, 'space: 'handle>(
fn write_scalar(
mut frame: AtomSpaceWriter<'handle, 'space>,
value: Self::InternalType,
) -> Option<()> {
Expand All @@ -66,31 +75,38 @@ pub trait ScalarAtom: UriBound {
}
}

impl<'handle, 'space: 'handle, A: ScalarAtom> Atom<'handle, 'space> for A {
type ReadParameter = ();
type ReadHandle = A::InternalType;
type WriteParameter = A::InternalType;
type WriteHandle = ();

unsafe fn read(body: &'space AtomSpace, _: ()) -> Option<A::InternalType> {
<A as ScalarAtom>::read_scalar(body)
}

fn init(frame: AtomSpaceWriter<'handle, 'space>, value: A::InternalType) -> Option<()> {
<A as ScalarAtom>::write_scalar(frame, value)
}
}

/// Macro to atomate the definition of scalar atoms.
macro_rules! make_scalar_atom {
($atom:ty, $internal:ty, $uri:expr, $urid:expr) => {
unsafe impl UriBound for $atom {
const URI: &'static [u8] = $uri;
}

impl ScalarAtom for $atom {
impl<'handle, 'space: 'handle> ScalarAtom<'handle, 'space> for $atom {
type InternalType = $internal;
}

impl<'handle, 'space: 'handle> Atom<'handle, 'space> for $atom {
type ReadParameter = ();
type ReadHandle = &'handle $internal;
type WriteParameter = $internal;
type WriteHandle = ();

unsafe fn read(body: &'space AtomSpace, _: ()) -> Option<&'handle $internal> {
<Self as ScalarAtom>::read_scalar(body)
}

fn init(frame: AtomSpaceWriter<'handle, 'space>, value: $internal) -> Option<()> {
<Self as ScalarAtom>::write_scalar(frame, value)
}
}

impl<'handle, 'space: 'handle> BackAsSpace<'handle, 'space> for $atom {
fn back_as_space(value: &'handle $internal) -> &'handle AlignedSpace<u8> {
let bytes = AlignedSpace::from_slice(::core::slice::from_ref(value)).as_bytes();
AlignedSpace::from_slice(bytes)
}
}
};
}

Expand Down Expand Up @@ -165,33 +181,33 @@ mod tests {
use std::convert::TryFrom;
use urid::*;

fn test_scalar<A: ScalarAtom>(value: A::InternalType)
fn test_scalar<A, T>(value: T)
where
A::InternalType: PartialEq<A::InternalType>,
A::InternalType: std::fmt::Debug,
for<'space> A: ScalarAtom<'space, 'space, InternalType = T>,
T: PartialEq<T>,
T: std::fmt::Debug,
{
let map = HashURIDMapper::new();
let urid: URID<A> = map.map_type().unwrap();

let mut raw_space = VecSpace::<AtomHeader>::new_with_capacity(64);
let raw_space = raw_space.as_space_mut();

// writing
{
let mut space = SpaceCursor::new(raw_space.as_bytes_mut());
space.init_atom(urid, value).unwrap();
let foo = space.init_atom(urid, value).unwrap();
}

// verifying
{
/*{
/// Generic version of the scalar atom structs.
#[repr(C, align(8))]
struct Scalar<B: Sized> {
atom: sys::LV2_Atom,
body: B,
}
let scalar: &Scalar<A::InternalType> =
let scalar: &Scalar<A::WriteParameter> =
unsafe { raw_space.read().next_value().unwrap() };
assert_eq!(scalar.atom.type_, urid);
Expand All @@ -206,17 +222,17 @@ mod tests {
.read(urid, ())
.unwrap();
assert_eq!(read_value, value);
}
assert_eq!(*read_value, value);
}*/
}

#[test]
fn test_scalars() {
test_scalar::<Double>(42.0);
test_scalar::<Float>(42.0);
test_scalar::<Long>(42);
test_scalar::<Int>(42);
test_scalar::<Bool>(1);
test_scalar::<AtomURID>(URID::try_from(1).unwrap());
test_scalar::<Double, _>(42.0);
test_scalar::<Float, _>(42.0);
test_scalar::<Long, _>(42);
test_scalar::<Int, _>(42);
test_scalar::<Bool, _>(1);
test_scalar::<AtomURID, _>(URID::try_from(1).unwrap());
}
}
4 changes: 2 additions & 2 deletions atom/src/atoms/sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,11 @@ mod tests {

let (stamp, atom) = reader.next().unwrap();
assert_eq!(stamp, TimeStamp::Frames(0));
assert_eq!(atom.read::<Int>(urids.atom.int, ()).unwrap(), 42);
assert_eq!(*atom.read::<Int>(urids.atom.int, ()).unwrap(), 42);

let (stamp, atom) = reader.next().unwrap();
assert_eq!(stamp, TimeStamp::Frames(1));
assert_eq!(atom.read::<Long>(urids.atom.long, ()).unwrap(), 17);
assert_eq!(*atom.read::<Long>(urids.atom.long, ()).unwrap(), 17);

assert!(reader.next().is_none());
}
Expand Down
10 changes: 5 additions & 5 deletions atom/src/atoms/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ use std::mem::{size_of, MaybeUninit};
/// An atom containg an array of scalar atom bodies.
///
/// [See also the module documentation.](index.html)
pub struct Vector<C: ScalarAtom> {
pub struct Vector<C> {
child: PhantomData<C>,
}

unsafe impl<C: ScalarAtom> UriBound for Vector<C> {
unsafe impl<C> UriBound for Vector<C> {
const URI: &'static [u8] = sys::LV2_ATOM__Vector;
}

impl<'handle, 'space: 'handle, C: ScalarAtom> Atom<'handle, 'space> for Vector<C>
impl<'handle, 'space: 'handle, C: ScalarAtom<'handle, 'space>> Atom<'handle, 'space> for Vector<C>
where
C: 'space,
{
Expand Down Expand Up @@ -92,12 +92,12 @@ where
/// Handle to append elements to a vector.
///
/// This works by allocating a slice of memory behind the vector and then writing your data to it.
pub struct VectorWriter<'handle, 'space, A: ScalarAtom> {
pub struct VectorWriter<'handle, 'space, A: ScalarAtom<'handle, 'space>> {
frame: AtomSpaceWriter<'handle, 'space>,
type_: PhantomData<A>,
}

impl<'handle, 'space, A: ScalarAtom> VectorWriter<'handle, 'space, A> {
impl<'handle, 'space, A: ScalarAtom<'handle, 'space>> VectorWriter<'handle, 'space, A> {
/// Push a single value to the vector.
#[inline]
pub fn push(&mut self, child: A::InternalType) -> Option<&mut A::InternalType> {
Expand Down
22 changes: 15 additions & 7 deletions atom/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,16 @@ pub mod prelude {
pub use crate::{atoms::AtomURIDCollection, Atom, UnidentifiedAtom};
}

trait AtomHandle<'a> {
type Handle: 'a;
}

/// Atom type.
///
/// This is the foundation of this crate: Types that implement `Atom` define the reading and writing functions for an atom type. However, these types will never be constructed; They are only names to be used for generic type arguments.
///
/// This trait has two lifetime parameters: The first one is the lifetime of the atom in memory. In practice, this will often be `'static`, but it's good to keep it generic for testing purposes. The second parameter is the lifetime of the `MutSpace` borrowed by the `FramedMutSpace` parameter in the `write` method. Since the `WriteParameter` may contain this `FramedMutSpace`, it has to be assured that it lives long enough. Since the referenced `MutSpace` also has to borrow the atom, it may not live longer than the atom.
pub trait Atom<'handle, 'space: 'handle>: UriBound {
pub trait Atom: UriBound {
/// The atom-specific parameter of the `read` function.
///
/// If your atom does not need a reading parameter, you may set it to `()`.
Expand All @@ -106,7 +110,7 @@ pub trait Atom<'handle, 'space: 'handle>: UriBound {
/// The return value of the `read` function.
///
/// It may contain a reference to the atom and therefore may not outlive it.
type ReadHandle: 'handle;
type ReadHandle: for<'a> AtomHandle<'a>;

/// The atom-specific parameter of the `write` function.
///
Expand All @@ -116,7 +120,7 @@ pub trait Atom<'handle, 'space: 'handle>: UriBound {
/// The return value of the `write` function.
///
/// It may contain a reference to a `MutSpace` and therefore may not outlive it.
type WriteHandle: 'handle;
type WriteHandle: for<'a> AtomHandle<'a>;

/// Reads the body of the atom.
///
Expand All @@ -128,10 +132,10 @@ pub trait Atom<'handle, 'space: 'handle>: UriBound {
///
/// The caller needs to ensure that the given [`Space`] contains a valid instance of this atom,
/// or the resulting `ReadHandle` will be completely invalid, and Undefined Behavior will happen.
unsafe fn read(
unsafe fn read<'handle, 'space: 'handle>(
body: &'space AtomSpace,
parameter: Self::ReadParameter,
) -> Option<Self::ReadHandle>;
) -> Option<<Self::ReadHandle as AtomHandle<'handle>>::Handle>;

/// Initialize the body of the atom.
///
Expand All @@ -141,10 +145,14 @@ pub trait Atom<'handle, 'space: 'handle>: UriBound {
/// The frame of the atom was already initialized, containing the URID.
///
/// If space is insufficient, you may not panic and return `None` instead. The written results are assumed to be malformed.
fn init(
fn init<'handle, 'space: 'handle>(
frame: AtomSpaceWriter<'handle, 'space>,
parameter: Self::WriteParameter,
) -> Option<Self::WriteHandle>;
) -> Option<<Self::WriteHandle as AtomHandle<'handle>>::Handle>;
}

pub trait BackAsSpace: Atom {
fn back_as_space(value: Self::ReadHandle) -> &'handle AlignedSpace<u8>;
}

/// An atom of yet unknown type.
Expand Down
2 changes: 1 addition & 1 deletion atom/src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ mod tests {
.read(urids.chunk, ())
.unwrap();
let reader = unsafe { AtomPort::input_from_raw(NonNull::from(chunk).cast(), 0) };
assert_eq!(reader.read::<Int>(urids.int, ()).unwrap(), 42);
assert_eq!(*reader.read::<Int>(urids.int, ()).unwrap(), 42);
}
}
}
4 changes: 2 additions & 2 deletions atom/src/space/allocatable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ pub trait SpaceAllocator<'space>: SpaceAllocatorImpl<'space> + Sized {
}

#[inline]
fn init_atom<'handle, A: Atom<'handle, 'space>>(
&'handle mut self,
fn init_atom<'handle, 'a: 'handle, A: Atom<'handle, 'space>>(
&'a mut self,
atom_type: URID<A>,
write_parameter: A::WriteParameter,
) -> Option<A::WriteHandle>
Expand Down
2 changes: 1 addition & 1 deletion atom/src/space/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub struct SpaceCursor<'a> {
}

impl<'a> SpaceCursor<'a> {
pub fn new(data: &'a mut [u8]) -> Self {
pub fn new<'b: 'a>(data: &'b mut [u8]) -> Self {
Self {
data,
allocated_length: 0,
Expand Down
5 changes: 3 additions & 2 deletions buf-size/src/buffer_sizes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ impl BufferSizes {
options: &OptionsList,
urids: &BufferSizesURIDCollection,
) -> Self {
BufferSizes {
todo!()
/*BufferSizes {
min_block_length: options
.read(urids.min_block_length, urids.atom_int, ())
.map(|x| x.get()),
Expand All @@ -46,6 +47,6 @@ impl BufferSizes {
sequence_size: options
.read(urids.sequence_size, urids.atom_int, ())
.map(|x| x.get()),
}
}*/
}
}
8 changes: 5 additions & 3 deletions buf-size/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ macro_rules! make_option {
}

impl lv2_options::OptionType for $name {
type AtomType = lv2_atom::scalar::Int;
type AtomType = lv2_atom::atoms::scalar::Int;

#[inline]
fn from_option_value<'a>(
value: <lv2_atom::scalar::Int as Atom<'a, 'a>>::ReadHandle,
value: <lv2_atom::atoms::scalar::Int as Atom<'a, 'a>>::ReadHandle,
) -> Option<Self> {
Some(Self((*value)))
}

#[inline]
fn as_option_value<'a>(&'a self) -> <lv2_atom::scalar::Int as Atom<'a, 'a>>::ReadHandle {
fn as_option_value<'a>(
&'a self,
) -> <lv2_atom::atoms::scalar::Int as Atom<'a, 'a>>::ReadHandle {
&self.0
}
}
Expand Down
Loading

0 comments on commit 4a80d43

Please sign in to comment.