1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
//! This module contains traits that are implemented by the generated code for
//! structs and archive resources.
//!
//! flatdata's code generator translates a flatdata schema to Rust code. The
//! generated code contains all schema definitions embedded as strings, and for
//! each schema element it implements all needed methods and traits.
//!
//! ## Structs
//!
//! For a flatdata struct, let's say `SomeData`, there are three generated
//! types in Rust: `SomeData`, SomeDataRef` and SomeDataRefMut`. The former
//! type is used to to create the latter two. `SomeDataRef` is used to read
//! data from a serialized archive, `SomeDataRefMut` to write data to archive.
//!
//! ## Indexes and variadic types
//!
//! A `MultiVector` is a heterogeneous container which consists of indexed
//! items, each containing several elements of different types (cf.
//! [`MultiVector`]). For each multivector resource in a flatdata archive
//! the generator creates a type with the same name and a type with suffix
//! `Ref`. The former is used as template parameter of containers
//! `MultiVector` and `MultiArrayView`. They implement the traits `VariadicRef`
//! resp. `VariadicStruct`. Additionally, the multivector is indexed by
//! a struct which is automatically generated flatdata struct. It implements
//! the trait `Index` and `IndexRef`.
//!
//! [`MultiVector`]: struct.MultiVector.html
use std::fmt::Debug;
#[doc(hidden)]
pub use std::marker;
/// A factory trait used to bind lifetime to Ref implementations.
///
/// Vector/ArrayView-like classes cannot be directly implemented over the
/// structs since that binds lifetime too early. Instead this generic factory
/// and Higher-Rank-Trait-Bounds are used to emulate higher-kinded-generics.
pub trait Struct: Debug {
/// Create a new struct
///
/// # Safety
/// If the struct is not self-contained (NoOverlap),
/// and there is no directly subsequent structure in memory,
/// then the resulting instance's data must not be accessed
unsafe fn create_unchecked() -> Self;
/// Size of an object of this type in bytes.
const SIZE_IN_BYTES: usize;
/// Whether this structs requires data of the next instance
const IS_OVERLAPPING_WITH_NEXT: bool;
}
/// Marks structs that can be used stand-alone, e.g. no range
///
/// # Safety
///
/// Safe only if the struct does not any memory outside of its own memory range
/// E.g. @range annotations use the next struct's memory and must not implement this
pub unsafe trait NoOverlap {}
/// Marks structs that cannot be used stand-alone, e.g. no range
pub trait Overlap {}
/// A specialized Struct factory producing Index items.
/// Used primarily by the MultiVector/MultiArrayView.
pub trait IndexStruct: Struct {
/// Provide getter for index
fn range(&self) -> std::ops::Range<usize>;
/// Provide setter for index
fn set_index(&mut self, value: usize);
}
/// Index specifying a variadic type of `MultiArrayView`.
pub type TypeIndex = u8;
/// A type used as element of `MultiArrayView`.
///
/// Implemented by an enum type.
pub trait VariadicRef: Clone + Debug + PartialEq {
/// Returns size in bytes of the current variant type.
///
/// Since a variadic struct can contain types of different sized, this is a
/// method based on the current value type.
fn size_in_bytes(&self) -> usize;
}
/// A type used as element of 'MultiArrayView'.
///
/// Provides the index type that should be used in the container.
pub trait VariadicIndex {
/// Index type
type Index: IndexStruct;
}
/// A type used to create VariadicStructs.
///
/// Vector/ArrayView-like classes cannot be directly implemented over the
/// structs since that binds lifetime too early. Instead this generic factory
/// and Higher-Rank-Trait-Bounds are used to emulate higher-kinded-generics.
pub trait VariadicStruct<'a>: Clone {
/// Reader type
type Item: VariadicRef;
/// Creates a reader for specific type of data.
fn create(data: TypeIndex, _: &'a [u8]) -> Self::Item;
/// Associated type used for building an item in `MultiVector` based on
/// this variadic type.
///
/// The builder is returned by
/// [`MultiVector::grow`](struct.MultiVector.html#method.grow)
/// method. It provides convenient methods `add_{variant_name}` for each
/// enum variant.
type ItemMut;
/// Creates a builder for a list of VariadicRef.
fn create_mut(data: &'a mut Vec<u8>) -> Self::ItemMut;
}
/// Shortcut trait for VariadicStructs that are able to produce references of
/// any given lifetime
///
/// Equivalent to ```for<'a> VariadicStruct<'a>'''
pub trait VariadicRefFactory: for<'a> VariadicStruct<'a> + VariadicIndex {}
impl<T> VariadicRefFactory for T
where
T: for<'a> VariadicStruct<'a>,
T: VariadicIndex,
{
}
#[cfg(test)]
mod test {
use super::*;
use crate::test::{A, R};
#[test]
fn test_debug() {
let a = A::new();
let output = format!("{:?}", a);
assert_eq!(output, "A { x: 0, y: 0, e: Value }");
}
#[test]
fn test_range() {
assert_eq!(<R as Struct>::IS_OVERLAPPING_WITH_NEXT, true);
}
}