From 0e9a4284e965809ce3400cf325af583d774aed9a Mon Sep 17 00:00:00 2001 From: Christian Vetter Date: Sat, 11 Apr 2020 11:03:17 +0200 Subject: [PATCH] Use transparent types in flatdat-rs to remove need for Ref/RefMut Note: This is a breaking change! Changes: * A struct transparently wraps a byte array of correct size * Instead of Ref/RefMute &Struct and &mut Struct are used * ArrayView is replaced by native slices * Archives store members with 'static lifetime, instead of constructing them all the time from pointers Signed-off-by: Christian Vetter --- .../generator/templates/rust/archive.jinja2 | 153 +- .../generator/templates/rust/index.jinja2 | 10 +- .../generator/templates/rust/rust.jinja2 | 1 + .../generator/templates/rust/structure.jinja2 | 147 +- .../generator/templates/rust/variadic.jinja2 | 22 +- .../rust_expectations/archives/comments.rs | 101 +- .../rust_expectations/archives/empty.rs | 15 +- .../rust_expectations/archives/multivector.rs | 807 +++++------ .../rust_expectations/archives/namespaces.rs | 527 ++++--- .../rust_expectations/archives/ranges.rs | 142 +- .../rust_expectations/archives/raw_data.rs | 29 +- .../rust_expectations/archives/references.rs | 520 ++++--- .../rust_expectations/archives/struct.rs | 185 ++- .../rust_expectations/archives/subarchive.rs | 51 +- .../rust_expectations/archives/vector.rs | 182 +-- .../rust_expectations/constants/namespaces.rs | 1 + .../rust_expectations/enums/default_width.rs | 1128 ++++++++------- .../rust_expectations/enums/namespaces.rs | 284 ++-- .../rust_expectations/enums/structs.rs | 1132 ++++++++------- .../rust_expectations/structs/comments.rs | 298 ++-- .../structs/default_width.rs | 1128 ++++++++------- .../rust_expectations/structs/integers.rs | 1128 ++++++++------- .../rust_expectations/structs/namespaces.rs | 283 ++-- .../rust_expectations/structs/unaligned.rs | 1232 ++++++++--------- flatdata-rs/lib/src/arrayview.rs | 332 +---- flatdata-rs/lib/src/error.rs | 3 + flatdata-rs/lib/src/lib.rs | 9 +- flatdata-rs/lib/src/multiarrayview.rs | 39 +- flatdata-rs/lib/src/multivector.rs | 30 +- flatdata-rs/lib/src/storage.rs | 45 +- flatdata-rs/lib/src/structbuf.rs | 150 -- flatdata-rs/lib/src/structs.rs | 83 +- flatdata-rs/lib/src/test/test_generated.rs | 708 ++++------ flatdata-rs/lib/src/vector.rs | 220 ++- flatdata-rs/tests/coappearances/src/lib.rs | 64 +- .../tests/features/src/archives/ranges.rs | 6 +- .../src/archives/struct_in_archive.rs | 12 +- .../tests/features/src/archives/vector.rs | 4 +- .../tests/features/src/enums/namespaces.rs | 8 +- .../tests/features/src/enums/structs.rs | 48 +- .../tests/features/src/structs/integers.rs | 96 +- .../tests/features/src/structs/unaligned.rs | 96 +- 42 files changed, 5239 insertions(+), 6220 deletions(-) delete mode 100644 flatdata-rs/lib/src/structbuf.rs diff --git a/flatdata-generator/flatdata/generator/templates/rust/archive.jinja2 b/flatdata-generator/flatdata/generator/templates/rust/archive.jinja2 index a59ef6ac..31644c55 100644 --- a/flatdata-generator/flatdata/generator/templates/rust/archive.jinja2 +++ b/flatdata-generator/flatdata/generator/templates/rust/archive.jinja2 @@ -19,20 +19,25 @@ pub struct {{archive.name}} { _storage: ::std::rc::Rc, {% for r in archive.resources | supported_resources %} - {{r.name}}: {% if r.optional %}Option<{% endif %}{% if [r] | instance_resources or [r] | vector_resources or [r] | rawdata_resources %}flatdata::MemoryDescriptor{% elif [r] | multivector_resources %}(flatdata::MemoryDescriptor, flatdata::MemoryDescriptor){% elif [r] | subarchive_resources %}{{ fully_qualified_name(archive, r.target.node) }}{% endif %}{% if r.optional %}>{% endif %}, + {{r.name}} : {% if r.optional %}Option<{% endif %} + {%- if [r] | vector_resources -%} + &'static [{{fully_qualified_name(archive, r.referenced_structures[0].node)}}] + {%- elif [r] | instance_resources -%} + &'static {{fully_qualified_name(archive, r.referenced_structures[0].node)}} + {%- elif [r] | rawdata_resources -%} + flatdata::RawData<'static> + {%- elif [r] | multivector_resources -%} + flatdata::MultiArrayView<'static, {{r.name | snake_to_upper_camel_case}}> + {%- elif [r] | rawdata_resources -%} + flatdata::MemoryDescriptor + {%- elif [r] | subarchive_resources -%} + {{ fully_qualified_name(archive, r.target.node) }} + {% endif %} + {% if r.optional %}>{% endif %}, {% endfor %} } impl {{archive.name}} { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } @@ -42,99 +47,52 @@ impl {{archive.name}} { {% if r.doc %} {{ r.doc | rust_doc }} {% endif %} - {% if r.optional %} #[inline] - pub fn {{r.name}}(&self) -> Option { - self.{{r.name}}.as_ref().map(|mem_desc| flatdata::RawData::new({unsafe {mem_desc.as_bytes()} })) + pub fn {{r.name}}(&self) -> {% if r.optional %}Option{% else %}flatdata::RawData{% endif %} { + self.{{r.name}} } - {% else %} - #[inline] - pub fn {{r.name}}(&self) -> flatdata::RawData { - flatdata::RawData::new(unsafe {self.{{r.name}}.as_bytes()}) - } - {% endif %} {% elif [r] | instance_resources %} {% set t = fully_qualified_name(archive, r.referenced_structures[0].node) %} {% if r.doc %} {{ r.doc | rust_doc }} {% endif %} - {% if r.optional %} - #[inline] - pub fn {{r.name}}(&self) -> Option<<{{t}} as flatdata::Struct>::Item> - { - self.{{r.name}}.as_ref().map(|mem_desc| {<{{t}} as flatdata::Struct>::create(&unsafe {mem_desc.as_bytes()})}) - } - {% else %} #[inline] - pub fn {{r.name}}(&self) -> <{{t}} as flatdata::Struct>::Item - { - <{{t}} as flatdata::Struct>::create(&unsafe {self.{{r.name}}.as_bytes()}) + pub fn {{r.name}}(&self) -> {% if r.optional %}Option<&{{t}}>{% else %}&{{t}}{% endif %} { + self.{{r.name}} } - {% endif %} {% elif [r] | vector_resources %} {% set t = fully_qualified_name(archive, r.referenced_structures[0].node) %} {% if r.doc %} {{ r.doc | rust_doc }} {% endif %} - {% if r.optional %} #[inline] - pub fn {{r.name}}(&self) -> Option> - { - self.{{r.name}}.as_ref().map(|x|flatdata::ArrayView::new(unsafe {x.as_bytes()})) - } - {% else %} - #[inline] - pub fn {{r.name}}(&self) -> flatdata::ArrayView<{{t}}> - { - flatdata::ArrayView::new(&unsafe {self.{{r.name}}.as_bytes()}) + pub fn {{r.name}}(&self) -> {% if r.optional %}Option<&[{{t}}]>{% else %}&[{{t}}]{% endif %} { + self.{{r.name}} } - {% endif %} {% elif [r] | multivector_resources %} {% set t = r.name | snake_to_upper_camel_case %} {% if r.doc %} {{ r.doc | rust_doc }} {% endif %} - {% if r.optional %} - #[inline] - pub fn {{r.name}}(&self) -> Option> - { - self.{{r.name}}.as_ref() - .map(|(index, data)|{ - flatdata::MultiArrayView::new(flatdata::ArrayView::new(unsafe {index.as_bytes()}), unsafe {data.as_bytes()}) - }) - } - {% else %} #[inline] - pub fn {{r.name}}(&self) -> flatdata::MultiArrayView<{{t}}> - { - flatdata::MultiArrayView::new( - flatdata::ArrayView::new(&unsafe {self.{{r.name}}.0.as_bytes()}), - &unsafe {self.{{r.name}}.1.as_bytes()}, - ) + pub fn {{r.name}}(&self) -> {% if r.optional %}Option<&flatdata::MultiArrayView<{{t}}>>{% else %}&flatdata::MultiArrayView<{{t}}>{% endif %} { + {%+ if r.optional %}self.{{r.name}}.as_ref(){% else %}&self.{{r.name}}{% endif %} + } - {% endif %} {% elif [r] | subarchive_resources %} {% set t = fully_qualified_name(archive, r.target.node) %} {% if r.doc %} {{ r.doc | rust_doc }} {% endif %} - {% if r.optional %} - #[inline] - pub fn {{r.name}}(&self) -> Option<&{{t}}> - { - self.{{r.name}}.as_ref() - } - {% else %} #[inline] - pub fn {{r.name}}(&self) -> &{{t}} - { - &self.{{r.name}} + pub fn {{r.name}}(&self) -> {% if r.optional %}Option<&{{t}}>{% else %}&{{t}}{% endif %} { + {%+ if r.optional %}self.{{r.name}}.as_ref(){% else %}&self.{{r.name}}{% endif %} + } - {% endif %} {% endif %} {% endfor %} @@ -157,23 +115,46 @@ impl flatdata::Archive for {{archive.name}} { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; {% for r in archive.resources | supported_resources %} - {% if [r] | instance_resources or [r] | vector_resources or [r] | rawdata_resources %} - let {{r.name}} = Self::read_resource(&*storage, "{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }}){% if r.optional %}.ok(){% else %}?{% endif %}; + {% if [r] | vector_resources %} + {% set t = fully_qualified_name(archive, r.referenced_structures[0].node) %} + let resource = extend(storage.read("{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }})); + let {{r.name}} = resource.map(|x| <&[{{t}}]>::from_bytes(x)){% if r.optional %}.ok().transpose()?{% else %}??{% endif %}; + {% elif [r] | instance_resources %} + {% set t = fully_qualified_name(archive, r.referenced_structures[0].node) %} + let resource = extend(storage.read("{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }})); + let {{r.name}} = resource.map(|x| {{t}}::from_bytes_slice(x)){% if r.optional %}.ok().transpose()?{% else %}??{% endif %}; + {% elif [r] | rawdata_resources %} + let resource = extend(storage.read("{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }})); + let {{r.name}} = resource.map(|x| flatdata::RawData::new(x)){% if r.optional %}.ok(){% else %}?{% endif %}; {% elif [r] | multivector_resources %} + {% set i = fully_qualified_name(archive, r.index_reference.node) %} let {{r.name}} = { let index_schema = &format!("index({})", schema::{{ archive_ns }}::resources::{{ r.name | upper }}); - let index = Self::read_resource(&*storage, "{{r.name}}_index", &index_schema){% if r.optional %}.ok(){% else %}?{% endif %}; - let data = Self::read_resource(&*storage, "{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }}){% if r.optional %}.ok(){% else %}?{% endif %}; - {%- if r.optional %} - match (index, data) { - (Some(index), Some(data)) => Some((index, data)), - _ => None, - } - {%- else %} - (index, data) + let index = extend(storage.read("{{r.name}}_index", &index_schema)); + let data = extend(storage.read("{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }})); + let result = match (index, data) { + (Ok(index), Ok(data)) => { + Ok(flatdata::MultiArrayView::new( + <&[{{i}}]>::from_bytes(index)?, + data + )) + } + (Ok(_), Err(x)) | (Err(x), Ok(_)) => {return Err(x);} + (Err(x), Err(_)) => Err(x), + }; + {% if r.optional %} + result.ok() + {% else %} + result? {% endif %} }; {% elif [r] | subarchive_resources %} @@ -217,10 +198,9 @@ impl {{archive.name}}Builder { /// Stores [`{{r.name}}`] in the archive. /// /// [`{{r.name}}`]: struct.{{archive.name}}.html#method.{{r.name}} - pub fn set_{{r.name}}(&self, resource: <{{t}} as flatdata::Struct>::Item) -> ::std::io::Result<()> { - let data = unsafe { - ::std::slice::from_raw_parts(resource.data, <{{t}} as flatdata::Struct>::SIZE_IN_BYTES) - }; + /// Stores [`{{r.name}}`] in the archive. + pub fn set_{{r.name}}(&self, resource: &{{t}}) -> ::std::io::Result<()> { + let data = resource.as_bytes(); self.storage.write("{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }}, data) } @@ -230,8 +210,9 @@ impl {{archive.name}}Builder { /// Stores [`{{r.name}}`] in the archive. /// /// [`{{r.name}}`]: struct.{{archive.name}}.html#method.{{r.name}} - pub fn set_{{ r.name }}(&self, vector: &flatdata::ArrayView<{{t}}>) -> ::std::io::Result<()> { - self.storage.write("{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }}, vector.as_ref()) + pub fn set_{{ r.name }}(&self, vector: &[{{t}}]) -> ::std::io::Result<()> { + use flatdata::SliceExt; + self.storage.write("{{r.name}}", schema::{{ archive_ns }}::resources::{{ r.name | upper }}, vector.as_bytes()) } /// Opens [`{{r.name}}`] in the archive for buffered writing. diff --git a/flatdata-generator/flatdata/generator/templates/rust/index.jinja2 b/flatdata-generator/flatdata/generator/templates/rust/index.jinja2 index f8023f23..cbe902f4 100644 --- a/flatdata-generator/flatdata/generator/templates/rust/index.jinja2 +++ b/flatdata-generator/flatdata/generator/templates/rust/index.jinja2 @@ -4,16 +4,16 @@ {# multivector index structs #} {{ structure.declaration(index) }} -impl<'a> flatdata::IndexStruct<'a> for {{index.name}} { +impl flatdata::IndexStruct for {{index.name}} { #[inline] - fn range(data: Self::Item) -> std::ops::Range { - let range = data.range(); + fn range(&self) -> std::ops::Range { + let range = self.range(); range.start as usize..range.end as usize } #[inline] - fn set_index(mut data: Self::ItemMut, value: usize) { - data.set_value(value as u64); + fn set_index(&mut self, value: usize) { + self.set_value(value as u64); } } {% endmacro %} diff --git a/flatdata-generator/flatdata/generator/templates/rust/rust.jinja2 b/flatdata-generator/flatdata/generator/templates/rust/rust.jinja2 index 7e7ee4bd..6b4c2213 100644 --- a/flatdata-generator/flatdata/generator/templates/rust/rust.jinja2 +++ b/flatdata-generator/flatdata/generator/templates/rust/rust.jinja2 @@ -8,6 +8,7 @@ {%- for ns in tree.root.children recursive %} {%- if ns | is_namespace %} +#[cfg_attr(rustfmt, rustfmt_skip)] {% if ns | is_builtin_namespace %} #[doc(hidden)] {% else %} diff --git a/flatdata-generator/flatdata/generator/templates/rust/structure.jinja2 b/flatdata-generator/flatdata/generator/templates/rust/structure.jinja2 index 2b337d63..dbb7f3a6 100644 --- a/flatdata-generator/flatdata/generator/templates/rust/structure.jinja2 +++ b/flatdata-generator/flatdata/generator/templates/rust/structure.jinja2 @@ -1,61 +1,89 @@ {%- macro declaration(struct) %} - {% if struct.doc %} {{ struct.doc | rust_doc }} {% endif %} -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`{{struct.name}}Ref`] for the read-only access, and -/// * [`{{struct.name}}Mut`] for the mutable access -/// -/// to the `{{struct.name}}` data. -/// -/// [`{{struct.name}}Ref`]: struct.{{struct.name}}Ref.html -/// [`{{struct.name}}Mut`]: struct.{{struct.name}}Mut.html -#[derive(Clone, Debug)] -pub struct {{struct.name}} {} - -/// Read-only access to [`{{struct.name}}`]. -/// -/// [`{{struct.name}}`]: struct.{{struct.name}}.html -#[derive(Clone, Copy)] -pub struct {{struct.name}}Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +#[repr(transparent)] +{% if not struct | has_range %} +#[derive(Clone)] +{% endif %} +pub struct {{struct.name}} { + data: [u8; {{ struct.size_in_bytes }}], } -impl<'a> flatdata::Struct<'a> for {{ struct.name }} -{ +impl {{ struct.name }} { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; {{ struct.size_in_bytes }}]} + } +} + +impl flatdata::Struct for {{ struct.name }} { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; {{ struct.size_in_bytes }}]} + } + const SCHEMA: &'static str = schema::structs::{{ struct.name | camel_to_snake_case | upper }}; const SIZE_IN_BYTES: usize = {{ struct.size_in_bytes }}; const IS_OVERLAPPING_WITH_NEXT : bool = {% if struct | has_range %}true{%else%}false{%endif%}; +} - type Item = {{ struct.name }}Ref<'a>; +{% if not struct | has_range %} +impl {{ struct.name }} { + pub fn new( ) -> Self { + Self{data : [0; {{ struct.size_in_bytes }}]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; {{ struct.size_in_bytes }}]) -> &Self { + // Safety: This is safe since {{ struct.name }} is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; {{ struct.size_in_bytes }}]) -> &mut Self { + // Safety: This is safe since {{ struct.name }} is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = {{ struct.name }}Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < {{ struct.size_in_bytes }} { + assert_eq!(data.len(), {{ struct.size_in_bytes }}); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; {{ struct.size_in_bytes }}]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < {{ struct.size_in_bytes }} { + assert_eq!(data.len(), {{ struct.size_in_bytes }}); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; {{ struct.size_in_bytes }}]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; {{ struct.size_in_bytes }}] { + &self.data + } +} + +impl Default for {{ struct.name }} { + fn default( ) -> Self { + Self::new( ) } } -{% if not struct | has_range %} impl flatdata::NoOverlap for {{struct.name}} {} {% endif %} -impl<'a> {{ struct.name }}Ref<'a> { +impl {{ struct.name }} { {% for field in struct.fields %} {% if field.doc and not field.range %} {{ field.doc | rust_doc }} @@ -66,7 +94,7 @@ impl<'a> {{ struct.name }}Ref<'a> { {% endif %} #[inline] pub fn {{ field.name | escape_rust_keywords }}(&self) -> {{ field | field_type }} { - let value = flatdata_read_bytes!({{ field | primitive_type }}, self.data, {{ field.offset }}, {{ field.type.width }}); + let value = flatdata_read_bytes!({{ field | primitive_type }}, self.data.as_ptr(), {{ field.offset }}, {{ field.type.width }}); unsafe { std::mem::transmute::<{{ field | primitive_type }}, {{ field | field_type }}>(value) } } @@ -76,8 +104,8 @@ impl<'a> {{ struct.name }}Ref<'a> { {% endif %} #[inline] pub fn {{ field.range | escape_rust_keywords }}(&self) -> std::ops::Range<{{ field | field_type }}> { - let start = flatdata_read_bytes!({{ field.type.name }}, self.data, {{ field.offset }}, {{ field.type.width }}); - let end = flatdata_read_bytes!({{ field.type.name }}, self.data, {{ field.offset }} + {{ struct.size_in_bytes }} * 8, {{ field.type.width }}); + let start = flatdata_read_bytes!({{ field.type.name }}, self.data.as_ptr(), {{ field.offset }}, {{ field.type.width }}); + let end = flatdata_read_bytes!({{ field.type.name }}, self.data.as_ptr(), {{ field.offset }} + {{ struct.size_in_bytes }} * 8, {{ field.type.width }}); start..end } @@ -85,7 +113,7 @@ impl<'a> {{ struct.name }}Ref<'a> { {% endfor %} } -impl<'a> std::fmt::Debug for {{ struct.name }}Ref<'a> { +impl std::fmt::Debug for {{ struct.name }} { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("{{ struct.name }}") {% for field in struct.fields %} @@ -96,7 +124,7 @@ impl<'a> std::fmt::Debug for {{ struct.name }}Ref<'a> { } } -impl<'a> std::cmp::PartialEq for {{ struct.name }}Ref<'a> { +impl std::cmp::PartialEq for {{ struct.name }} { #[inline] fn eq(&self, other: &Self) -> bool { {% for field in struct.fields %} @@ -106,17 +134,7 @@ impl<'a> std::cmp::PartialEq for {{ struct.name }}Ref<'a> { } } -impl<'a> flatdata::Ref for {{ struct.name }}Ref<'a> {} - -/// Mutable access to [`{{struct.name}}`]. -/// -/// [`{{struct.name}}`]: struct.{{struct.name}}.html -pub struct {{ struct.name }}Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> {{ struct.name }}Mut<'a> { +impl {{ struct.name }} { {% for field in struct.fields %} {% set name = field.name | escape_rust_keywords %} {% if field.doc and not field.range %} @@ -127,25 +145,16 @@ impl<'a> {{ struct.name }}Mut<'a> { /// [`{{ field.range | escape_rust_keywords }}`]: struct.{{ struct.name }}Ref.html#method.{{ field.range | escape_rust_keywords }} {% endif %} #[inline] - pub fn {{ name }}(&self) -> {{ field | field_type }} { - let value = flatdata_read_bytes!({{ field | primitive_type }}, self.data, {{ field.offset }}, {{ field.type.width }}); - unsafe { std::mem::transmute::<{{ field | primitive_type }}, {{ field | field_type }}>(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_{{ name }}(&mut self, value: {{ field | field_type }}) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, {{ struct.size_in_bytes }}) - }; - flatdata_write_bytes!({{ field | primitive_type }}; value, buffer, {{ field.offset }}, {{ field.type.width }}) + flatdata_write_bytes!({{ field | primitive_type }}; value, self.data, {{ field.offset }}, {{ field.type.width }}) } {% endfor %} /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &{{ struct.name }}Ref) { + pub fn fill_from(&mut self, other: &{{ struct.name }}) { {% for field in struct.fields %} {% set name = field.name | escape_rust_keywords %} self.set_{{ name }}(other.{{ name }}()); @@ -153,12 +162,4 @@ impl<'a> {{ struct.name }}Mut<'a> { } } -impl<'a> std::fmt::Debug for {{ struct.name }}Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - {{ struct.name }}Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for {{ struct.name }}Mut<'a> {} - {%- endmacro %} diff --git a/flatdata-generator/flatdata/generator/templates/rust/variadic.jinja2 b/flatdata-generator/flatdata/generator/templates/rust/variadic.jinja2 index 36478f2c..8e864099 100644 --- a/flatdata-generator/flatdata/generator/templates/rust/variadic.jinja2 +++ b/flatdata-generator/flatdata/generator/templates/rust/variadic.jinja2 @@ -10,7 +10,7 @@ pub enum {{name}}Ref<'a> { {% for type in types %} #[allow(missing_docs)] - {{type.node.name }}(<{{fully_qualified_name(archive, type.node)}} as flatdata::Struct<'a>>::Item), + {{type.node.name }}(&'a {{fully_qualified_name(archive, type.node)}}), {%- endfor %} } @@ -29,7 +29,7 @@ impl<'a> flatdata::VariadicRef for {{name}}Ref<'a> { fn size_in_bytes(&self) -> usize { match *self { {% for type in types %} - {{name}}Ref::{{type.node.name}}(_) => <{{fully_qualified_name(archive, type.node)}} as flatdata::Struct<'a>>::SIZE_IN_BYTES, + {{name}}Ref::{{type.node.name}}(_) => <{{fully_qualified_name(archive, type.node)}} as flatdata::Struct>::SIZE_IN_BYTES, {% endfor %} } } @@ -52,14 +52,13 @@ impl<'a> {{name}}Builder<'a> { /// /// [`{{type.node.name}}`]: struct.{{type.node.name}}.html #[inline] - pub fn add_{{ type.node.name | camel_to_snake_case }}<'b>(&'b mut self) -> <{{inner_type}} as flatdata::Struct<'b>>::ItemMut { + pub fn add_{{ type.node.name | camel_to_snake_case }}<'b>(&'b mut self) -> &'b mut {{inner_type}} { let old_len = self.data.len(); - let increment = 1 + <{{inner_type}} as flatdata::Struct<'b>>::SIZE_IN_BYTES; + let increment = 1 + <{{inner_type}} as flatdata::Struct>::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = {{loop.index0}}; - <{{inner_type}} as flatdata::Struct<'b>>::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = {{loop.index0}}; + let slice = &mut self.data[1 + old_len..]; + {{inner_type}}::from_bytes_slice_mut(slice).expect("Logic error: Cannot create {{inner_type}} from slice") } {% endfor %} } @@ -89,9 +88,11 @@ impl<'a> {{name}}Builder<'a> { #[derive(Clone)] pub struct {{name}} {} -impl<'a> flatdata::VariadicStruct<'a> for {{name}} { +impl flatdata::VariadicIndex for {{name}} { type Index = {{ fully_qualified_name(archive, resource.index_reference.node) }}; +} +impl<'a> flatdata::VariadicStruct<'a> for {{name}} { type Item = {{name}}Ref<'a>; #[inline] @@ -99,7 +100,8 @@ impl<'a> flatdata::VariadicStruct<'a> for {{name}} { { match index { {% for type in types %} - {{loop.index0}} => {{name}}Ref::{{type.node.name}}(<{{fully_qualified_name(archive, type.node)}} as flatdata::Struct<'a>>::create(data)), + {% set inner_type = fully_qualified_name(archive, type.node) %} + {{loop.index0}} => {{name}}Ref::{{type.node.name}}({{inner_type}}::from_bytes_slice(&data).expect("Corrupted data")), {% endfor %} _ => panic!("invalid type index {} for variadic type {{name}}Ref", index), } diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/comments.rs b/flatdata-generator/tests/generators/rust_expectations/archives/comments.rs index e7271f52..d30ed706 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/comments.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/comments.rs @@ -1,20 +1,68 @@ +// Do not edit: This code was generated by flatdata's generator. +#[cfg_attr(rustfmt, rustfmt_skip)] +#[allow(missing_docs)] +pub mod n { + +#[doc(hidden)] +pub mod schema { +pub mod structs { +} + +pub mod foo { + +pub const FOO: &str = r#"namespace n { +archive Foo +{ + bar : raw_data; +} +} + +"#; + +pub mod resources { +pub const BAR: &str = r#"namespace n { +archive Foo +{ + bar : raw_data; +} +} + +"#; +} +} +pub mod bar { + +pub const BAR: &str = r#"namespace n { +archive Bar +{ + foo : raw_data; +} +} + +"#; + +pub mod resources { +pub const FOO: &str = r#"namespace n { +archive Bar +{ + foo : raw_data; +} +} + +"#; +} +} +} + + // This is a comment about foo #[derive(Clone)] pub struct Foo { _storage: ::std::rc::Rc, - bar: flatdata::MemoryDescriptor, + bar : flatdata::RawData<'static>, } impl Foo { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } @@ -22,7 +70,7 @@ impl Foo { // this is a comment about foo.bar #[inline] pub fn bar(&self) -> flatdata::RawData { - flatdata::RawData::new(unsafe {self.bar.as_bytes()}) + self.bar } } @@ -42,9 +90,16 @@ impl flatdata::Archive for Foo { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let bar = Self::read_resource(&*storage, "bar", schema::foo::resources::BAR)?; + let resource = extend(storage.read("bar", schema::foo::resources::BAR)); + let bar = resource.map(|x| flatdata::RawData::new(x))?; Ok(Self { _storage: storage, @@ -91,19 +146,10 @@ impl flatdata::ArchiveBuilder for FooBuilder { #[derive(Clone)] pub struct Bar { _storage: ::std::rc::Rc, - foo: flatdata::MemoryDescriptor, + foo : flatdata::RawData<'static>, } impl Bar { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } @@ -111,7 +157,7 @@ impl Bar { /// this is a comment about bar.foo #[inline] pub fn foo(&self) -> flatdata::RawData { - flatdata::RawData::new(unsafe {self.foo.as_bytes()}) + self.foo } } @@ -131,9 +177,16 @@ impl flatdata::Archive for Bar { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let foo = Self::read_resource(&*storage, "foo", schema::bar::resources::FOO)?; + let resource = extend(storage.read("foo", schema::bar::resources::FOO)); + let foo = resource.map(|x| flatdata::RawData::new(x))?; Ok(Self { _storage: storage, diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/empty.rs b/flatdata-generator/tests/generators/rust_expectations/archives/empty.rs index 2b4dfa66..1dd962ca 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/empty.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/empty.rs @@ -4,15 +4,6 @@ pub struct A { } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } @@ -33,6 +24,12 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/multivector.rs b/flatdata-generator/tests/generators/rust_expectations/archives/multivector.rs index 871eeff8..89d8aa43 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/multivector.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/multivector.rs @@ -1,63 +1,90 @@ -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`SRef`] for the read-only access, and -/// * [`SMut`] for the mutable access -/// -/// to the `S` data. -/// -/// [`SRef`]: struct.SRef.html -/// [`SMut`]: struct.SMut.html -#[derive(Clone, Debug)] -pub struct S {} +#[repr(transparent)] +#[derive(Clone)] +pub struct S { + data: [u8; 8], +} -/// Read-only access to [`S`]. -/// -/// [`S`]: struct.S.html -#[derive(Clone, Copy)] -pub struct SRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl S { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } } -impl<'a> flatdata::Struct<'a> for S -{ +impl flatdata::Struct for S { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } + const SCHEMA: &'static str = schema::structs::S; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = SRef<'a>; +impl S { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = SMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for S { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for S {} -impl<'a> SRef<'a> { +impl S { #[inline] pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for SRef<'a> { +impl std::fmt::Debug for S { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("S") .field("x", &self.x()) @@ -65,114 +92,113 @@ impl<'a> std::fmt::Debug for SRef<'a> { } } -impl<'a> std::cmp::PartialEq for SRef<'a> { +impl std::cmp::PartialEq for S { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() } } -impl<'a> flatdata::Ref for SRef<'a> {} - -/// Mutable access to [`S`]. -/// -/// [`S`]: struct.S.html -pub struct SMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> SMut<'a> { +impl S { #[inline] - pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &SRef) { + pub fn fill_from(&mut self, other: &S) { self.set_x(other.x()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct T { + data: [u8; 8], +} -impl<'a> std::fmt::Debug for SMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - SRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) +impl T { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} } } -impl<'a> flatdata::RefMut for SMut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`TRef`] for the read-only access, and -/// * [`TMut`] for the mutable access -/// -/// to the `T` data. -/// -/// [`TRef`]: struct.TRef.html -/// [`TMut`]: struct.TMut.html -#[derive(Clone, Debug)] -pub struct T {} - -/// Read-only access to [`T`]. -/// -/// [`T`]: struct.T.html -#[derive(Clone, Copy)] -pub struct TRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} +impl flatdata::Struct for T { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> flatdata::Struct<'a> for T -{ const SCHEMA: &'static str = schema::structs::T; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = TRef<'a>; +impl T { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since T is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since T is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = TMut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for T { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for T {} -impl<'a> TRef<'a> { +impl T { #[inline] pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for TRef<'a> { +impl std::fmt::Debug for T { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("T") .field("x", &self.x()) @@ -180,54 +206,27 @@ impl<'a> std::fmt::Debug for TRef<'a> { } } -impl<'a> std::cmp::PartialEq for TRef<'a> { +impl std::cmp::PartialEq for T { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() } } -impl<'a> flatdata::Ref for TRef<'a> {} - -/// Mutable access to [`T`]. -/// -/// [`T`]: struct.T.html -pub struct TMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> TMut<'a> { +impl T { #[inline] - pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &TRef) { + pub fn fill_from(&mut self, other: &T) { self.set_x(other.x()); } } -impl<'a> std::fmt::Debug for TMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - TRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for TMut<'a> {} - /// Enum for read-only heterogeneous access to elements in a /// bucket of the [`data`] resource. @@ -236,8 +235,8 @@ impl<'a> flatdata::RefMut for TMut<'a> {} #[derive(Clone, PartialEq)] pub enum DataRef<'a> { #[allow(missing_docs)] - S(>::Item), #[allow(missing_docs)] - T(>::Item),} + S(&'a super::n::S), #[allow(missing_docs)] + T(&'a super::n::T),} impl<'a> ::std::fmt::Debug for DataRef<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -252,8 +251,8 @@ impl<'a> flatdata::VariadicRef for DataRef<'a> { #[inline] fn size_in_bytes(&self) -> usize { match *self { - DataRef::S(_) => >::SIZE_IN_BYTES, - DataRef::T(_) => >::SIZE_IN_BYTES, + DataRef::S(_) => ::SIZE_IN_BYTES, + DataRef::T(_) => ::SIZE_IN_BYTES, } } } @@ -273,27 +272,25 @@ impl<'a> DataBuilder<'a> { /// /// [`S`]: struct.S.html #[inline] - pub fn add_s<'b>(&'b mut self) -> >::ItemMut { + pub fn add_s<'b>(&'b mut self) -> &'b mut super::n::S { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 0; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 0; + let slice = &mut self.data[1 + old_len..]; + super::n::S::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::S from slice") } /// Adds data of the type [`T`] to the bucket. /// /// [`T`]: struct.T.html #[inline] - pub fn add_t<'b>(&'b mut self) -> >::ItemMut { + pub fn add_t<'b>(&'b mut self) -> &'b mut super::n::T { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 1; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 1; + let slice = &mut self.data[1 + old_len..]; + super::n::T::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::T from slice") } } @@ -320,17 +317,19 @@ impl<'a> DataBuilder<'a> { #[derive(Clone)] pub struct Data {} -impl<'a> flatdata::VariadicStruct<'a> for Data { +impl flatdata::VariadicIndex for Data { type Index = super::_builtin::multivector::IndexType8; +} +impl<'a> flatdata::VariadicStruct<'a> for Data { type Item = DataRef<'a>; #[inline] fn create(index: flatdata::TypeIndex, data: &'a [u8]) -> Self::Item { match index { - 0 => DataRef::S(>::create(data)), - 1 => DataRef::T(>::create(data)), + 0 => DataRef::S(super::n::S::from_bytes_slice(&data).expect("Corrupted data")), + 1 => DataRef::T(super::n::T::from_bytes_slice(&data).expect("Corrupted data")), _ => panic!("invalid type index {} for variadic type DataRef", index), } } @@ -350,8 +349,8 @@ impl<'a> flatdata::VariadicStruct<'a> for Data { #[derive(Clone, PartialEq)] pub enum OptionalDataRef<'a> { #[allow(missing_docs)] - S(>::Item), #[allow(missing_docs)] - T(>::Item),} + S(&'a super::n::S), #[allow(missing_docs)] + T(&'a super::n::T),} impl<'a> ::std::fmt::Debug for OptionalDataRef<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -366,8 +365,8 @@ impl<'a> flatdata::VariadicRef for OptionalDataRef<'a> { #[inline] fn size_in_bytes(&self) -> usize { match *self { - OptionalDataRef::S(_) => >::SIZE_IN_BYTES, - OptionalDataRef::T(_) => >::SIZE_IN_BYTES, + OptionalDataRef::S(_) => ::SIZE_IN_BYTES, + OptionalDataRef::T(_) => ::SIZE_IN_BYTES, } } } @@ -387,27 +386,25 @@ impl<'a> OptionalDataBuilder<'a> { /// /// [`S`]: struct.S.html #[inline] - pub fn add_s<'b>(&'b mut self) -> >::ItemMut { + pub fn add_s<'b>(&'b mut self) -> &'b mut super::n::S { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 0; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 0; + let slice = &mut self.data[1 + old_len..]; + super::n::S::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::S from slice") } /// Adds data of the type [`T`] to the bucket. /// /// [`T`]: struct.T.html #[inline] - pub fn add_t<'b>(&'b mut self) -> >::ItemMut { + pub fn add_t<'b>(&'b mut self) -> &'b mut super::n::T { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 1; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 1; + let slice = &mut self.data[1 + old_len..]; + super::n::T::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::T from slice") } } @@ -434,17 +431,19 @@ impl<'a> OptionalDataBuilder<'a> { #[derive(Clone)] pub struct OptionalData {} -impl<'a> flatdata::VariadicStruct<'a> for OptionalData { +impl flatdata::VariadicIndex for OptionalData { type Index = super::_builtin::multivector::IndexType16; +} +impl<'a> flatdata::VariadicStruct<'a> for OptionalData { type Item = OptionalDataRef<'a>; #[inline] fn create(index: flatdata::TypeIndex, data: &'a [u8]) -> Self::Item { match index { - 0 => OptionalDataRef::S(>::create(data)), - 1 => OptionalDataRef::T(>::create(data)), + 0 => OptionalDataRef::S(super::n::S::from_bytes_slice(&data).expect("Corrupted data")), + 1 => OptionalDataRef::T(super::n::T::from_bytes_slice(&data).expect("Corrupted data")), _ => panic!("invalid type index {} for variadic type OptionalDataRef", index), } } @@ -464,8 +463,8 @@ impl<'a> flatdata::VariadicStruct<'a> for OptionalData { #[derive(Clone, PartialEq)] pub enum DataU64IndexRef<'a> { #[allow(missing_docs)] - S(>::Item), #[allow(missing_docs)] - T(>::Item),} + S(&'a super::n::S), #[allow(missing_docs)] + T(&'a super::n::T),} impl<'a> ::std::fmt::Debug for DataU64IndexRef<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -480,8 +479,8 @@ impl<'a> flatdata::VariadicRef for DataU64IndexRef<'a> { #[inline] fn size_in_bytes(&self) -> usize { match *self { - DataU64IndexRef::S(_) => >::SIZE_IN_BYTES, - DataU64IndexRef::T(_) => >::SIZE_IN_BYTES, + DataU64IndexRef::S(_) => ::SIZE_IN_BYTES, + DataU64IndexRef::T(_) => ::SIZE_IN_BYTES, } } } @@ -501,27 +500,25 @@ impl<'a> DataU64IndexBuilder<'a> { /// /// [`S`]: struct.S.html #[inline] - pub fn add_s<'b>(&'b mut self) -> >::ItemMut { + pub fn add_s<'b>(&'b mut self) -> &'b mut super::n::S { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 0; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 0; + let slice = &mut self.data[1 + old_len..]; + super::n::S::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::S from slice") } /// Adds data of the type [`T`] to the bucket. /// /// [`T`]: struct.T.html #[inline] - pub fn add_t<'b>(&'b mut self) -> >::ItemMut { + pub fn add_t<'b>(&'b mut self) -> &'b mut super::n::T { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 1; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 1; + let slice = &mut self.data[1 + old_len..]; + super::n::T::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::T from slice") } } @@ -548,17 +545,19 @@ impl<'a> DataU64IndexBuilder<'a> { #[derive(Clone)] pub struct DataU64Index {} -impl<'a> flatdata::VariadicStruct<'a> for DataU64Index { +impl flatdata::VariadicIndex for DataU64Index { type Index = super::_builtin::multivector::IndexType64; +} +impl<'a> flatdata::VariadicStruct<'a> for DataU64Index { type Item = DataU64IndexRef<'a>; #[inline] fn create(index: flatdata::TypeIndex, data: &'a [u8]) -> Self::Item { match index { - 0 => DataU64IndexRef::S(>::create(data)), - 1 => DataU64IndexRef::T(>::create(data)), + 0 => DataU64IndexRef::S(super::n::S::from_bytes_slice(&data).expect("Corrupted data")), + 1 => DataU64IndexRef::T(super::n::T::from_bytes_slice(&data).expect("Corrupted data")), _ => panic!("invalid type index {} for variadic type DataU64IndexRef", index), } } @@ -575,50 +574,29 @@ impl<'a> flatdata::VariadicStruct<'a> for DataU64Index { #[derive(Clone)] pub struct A { _storage: ::std::rc::Rc, - data: (flatdata::MemoryDescriptor, flatdata::MemoryDescriptor), - optional_data: Option<(flatdata::MemoryDescriptor, flatdata::MemoryDescriptor)>, - data_u64_index: (flatdata::MemoryDescriptor, flatdata::MemoryDescriptor), + data : flatdata::MultiArrayView<'static, Data>, + optional_data : Option>, + data_u64_index : flatdata::MultiArrayView<'static, DataU64Index>, } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn data(&self) -> flatdata::MultiArrayView - { - flatdata::MultiArrayView::new( - flatdata::ArrayView::new(&unsafe {self.data.0.as_bytes()}), - &unsafe {self.data.1.as_bytes()}, - ) + pub fn data(&self) -> &flatdata::MultiArrayView { + &self.data } #[inline] - pub fn optional_data(&self) -> Option> - { + pub fn optional_data(&self) -> Option<&flatdata::MultiArrayView> { self.optional_data.as_ref() - .map(|(index, data)|{ - flatdata::MultiArrayView::new(flatdata::ArrayView::new(unsafe {index.as_bytes()}), unsafe {data.as_bytes()}) - }) } #[inline] - pub fn data_u64_index(&self) -> flatdata::MultiArrayView - { - flatdata::MultiArrayView::new( - flatdata::ArrayView::new(&unsafe {self.data_u64_index.0.as_bytes()}), - &unsafe {self.data_u64_index.1.as_bytes()}, - ) + pub fn data_u64_index(&self) -> &flatdata::MultiArrayView { + &self.data_u64_index } } @@ -640,24 +618,61 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; let data = { let index_schema = &format!("index({})", schema::a::resources::DATA); - let index = Self::read_resource(&*storage, "data_index", &index_schema)?; - let data = Self::read_resource(&*storage, "data", schema::a::resources::DATA)?; (index, data) + let index = extend(storage.read("data_index", &index_schema)); + let data = extend(storage.read("data", schema::a::resources::DATA)); + let result = match (index, data) { + (Ok(index), Ok(data)) => { + Ok(flatdata::MultiArrayView::new( + <&[super::_builtin::multivector::IndexType8]>::from_bytes(index)?, + data + )) + } + (Ok(_), Err(x)) | (Err(x), Ok(_)) => {return Err(x);} + (Err(x), Err(_)) => Err(x), + }; + result? }; let optional_data = { let index_schema = &format!("index({})", schema::a::resources::OPTIONAL_DATA); - let index = Self::read_resource(&*storage, "optional_data_index", &index_schema).ok(); - let data = Self::read_resource(&*storage, "optional_data", schema::a::resources::OPTIONAL_DATA).ok(); match (index, data) { - (Some(index), Some(data)) => Some((index, data)), - _ => None, - } }; + let index = extend(storage.read("optional_data_index", &index_schema)); + let data = extend(storage.read("optional_data", schema::a::resources::OPTIONAL_DATA)); + let result = match (index, data) { + (Ok(index), Ok(data)) => { + Ok(flatdata::MultiArrayView::new( + <&[super::_builtin::multivector::IndexType16]>::from_bytes(index)?, + data + )) + } + (Ok(_), Err(x)) | (Err(x), Ok(_)) => {return Err(x);} + (Err(x), Err(_)) => Err(x), + }; + result.ok() + }; let data_u64_index = { let index_schema = &format!("index({})", schema::a::resources::DATA_U64_INDEX); - let index = Self::read_resource(&*storage, "data_u64_index_index", &index_schema)?; - let data = Self::read_resource(&*storage, "data_u64_index", schema::a::resources::DATA_U64_INDEX)?; (index, data) + let index = extend(storage.read("data_u64_index_index", &index_schema)); + let data = extend(storage.read("data_u64_index", schema::a::resources::DATA_U64_INDEX)); + let result = match (index, data) { + (Ok(index), Ok(data)) => { + Ok(flatdata::MultiArrayView::new( + <&[super::_builtin::multivector::IndexType64]>::from_bytes(index)?, + data + )) + } + (Ok(_), Err(x)) | (Err(x), Ok(_)) => {return Err(x);} + (Err(x), Err(_)) => Err(x), + }; + result? }; Ok(Self { @@ -733,9 +748,11 @@ impl flatdata::ArchiveBuilder for ABuilder { } +#[cfg_attr(rustfmt, rustfmt_skip)] #[doc(hidden)] pub mod _builtin { +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod multivector { @@ -748,77 +765,50 @@ pub const INDEX_TYPE64: &str = r#""#; } } - /// Builtin type to for MultiVector index -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`IndexType8Ref`] for the read-only access, and -/// * [`IndexType8Mut`] for the mutable access -/// -/// to the `IndexType8` data. -/// -/// [`IndexType8Ref`]: struct.IndexType8Ref.html -/// [`IndexType8Mut`]: struct.IndexType8Mut.html -#[derive(Clone, Debug)] -pub struct IndexType8 {} +#[repr(transparent)] +pub struct IndexType8 { + data: [u8; 1], +} -/// Read-only access to [`IndexType8`]. -/// -/// [`IndexType8`]: struct.IndexType8.html -#[derive(Clone, Copy)] -pub struct IndexType8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl IndexType8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } } -impl<'a> flatdata::Struct<'a> for IndexType8 -{ +impl flatdata::Struct for IndexType8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } + const SCHEMA: &'static str = schema::structs::INDEX_TYPE8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = true; - - type Item = IndexType8Ref<'a>; - - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } - } - - type ItemMut = IndexType8Mut<'a>; - - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } - } } -impl<'a> IndexType8Ref<'a> { +impl IndexType8 { /// First element of the range [`range`]. /// /// [`range`]: #method.range #[inline] pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 8); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } #[inline] pub fn range(&self) -> std::ops::Range { - let start = flatdata_read_bytes!(u64, self.data, 0, 8); - let end = flatdata_read_bytes!(u64, self.data, 0 + 1 * 8, 8); + let start = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 8); + let end = flatdata_read_bytes!(u64, self.data.as_ptr(), 0 + 1 * 8, 8); start..end } } -impl<'a> std::fmt::Debug for IndexType8Ref<'a> { +impl std::fmt::Debug for IndexType8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("IndexType8") .field("value", &self.value()) @@ -826,142 +816,88 @@ impl<'a> std::fmt::Debug for IndexType8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for IndexType8Ref<'a> { +impl std::cmp::PartialEq for IndexType8 { #[inline] fn eq(&self, other: &Self) -> bool { self.value() == other.value() } } -impl<'a> flatdata::Ref for IndexType8Ref<'a> {} - -/// Mutable access to [`IndexType8`]. -/// -/// [`IndexType8`]: struct.IndexType8.html -pub struct IndexType8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> IndexType8Mut<'a> { +impl IndexType8 { /// First element of the range [`range`]. /// /// [`range`]: struct.IndexType8Ref.html#method.range #[inline] - pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_value(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 8) + flatdata_write_bytes!(u64; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &IndexType8Ref) { + pub fn fill_from(&mut self, other: &IndexType8) { self.set_value(other.value()); } } -impl<'a> std::fmt::Debug for IndexType8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - IndexType8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for IndexType8Mut<'a> {} - -impl<'a> flatdata::IndexStruct<'a> for IndexType8 { +impl flatdata::IndexStruct for IndexType8 { #[inline] - fn range(data: Self::Item) -> std::ops::Range { - let range = data.range(); + fn range(&self) -> std::ops::Range { + let range = self.range(); range.start as usize..range.end as usize } #[inline] - fn set_index(mut data: Self::ItemMut, value: usize) { - data.set_value(value as u64); + fn set_index(&mut self, value: usize) { + self.set_value(value as u64); } } - /// Builtin type to for MultiVector index -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`IndexType16Ref`] for the read-only access, and -/// * [`IndexType16Mut`] for the mutable access -/// -/// to the `IndexType16` data. -/// -/// [`IndexType16Ref`]: struct.IndexType16Ref.html -/// [`IndexType16Mut`]: struct.IndexType16Mut.html -#[derive(Clone, Debug)] -pub struct IndexType16 {} +#[repr(transparent)] +pub struct IndexType16 { + data: [u8; 2], +} -/// Read-only access to [`IndexType16`]. -/// -/// [`IndexType16`]: struct.IndexType16.html -#[derive(Clone, Copy)] -pub struct IndexType16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl IndexType16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } } -impl<'a> flatdata::Struct<'a> for IndexType16 -{ +impl flatdata::Struct for IndexType16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } + const SCHEMA: &'static str = schema::structs::INDEX_TYPE16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = true; - - type Item = IndexType16Ref<'a>; - - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } - } - - type ItemMut = IndexType16Mut<'a>; - - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } - } } -impl<'a> IndexType16Ref<'a> { +impl IndexType16 { /// First element of the range [`range`]. /// /// [`range`]: #method.range #[inline] pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 16); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } #[inline] pub fn range(&self) -> std::ops::Range { - let start = flatdata_read_bytes!(u64, self.data, 0, 16); - let end = flatdata_read_bytes!(u64, self.data, 0 + 2 * 8, 16); + let start = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 16); + let end = flatdata_read_bytes!(u64, self.data.as_ptr(), 0 + 2 * 8, 16); start..end } } -impl<'a> std::fmt::Debug for IndexType16Ref<'a> { +impl std::fmt::Debug for IndexType16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("IndexType16") .field("value", &self.value()) @@ -969,142 +905,88 @@ impl<'a> std::fmt::Debug for IndexType16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for IndexType16Ref<'a> { +impl std::cmp::PartialEq for IndexType16 { #[inline] fn eq(&self, other: &Self) -> bool { self.value() == other.value() } } -impl<'a> flatdata::Ref for IndexType16Ref<'a> {} - -/// Mutable access to [`IndexType16`]. -/// -/// [`IndexType16`]: struct.IndexType16.html -pub struct IndexType16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> IndexType16Mut<'a> { +impl IndexType16 { /// First element of the range [`range`]. /// /// [`range`]: struct.IndexType16Ref.html#method.range #[inline] - pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_value(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 16) + flatdata_write_bytes!(u64; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &IndexType16Ref) { + pub fn fill_from(&mut self, other: &IndexType16) { self.set_value(other.value()); } } -impl<'a> std::fmt::Debug for IndexType16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - IndexType16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for IndexType16Mut<'a> {} - -impl<'a> flatdata::IndexStruct<'a> for IndexType16 { +impl flatdata::IndexStruct for IndexType16 { #[inline] - fn range(data: Self::Item) -> std::ops::Range { - let range = data.range(); + fn range(&self) -> std::ops::Range { + let range = self.range(); range.start as usize..range.end as usize } #[inline] - fn set_index(mut data: Self::ItemMut, value: usize) { - data.set_value(value as u64); + fn set_index(&mut self, value: usize) { + self.set_value(value as u64); } } - /// Builtin type to for MultiVector index -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`IndexType64Ref`] for the read-only access, and -/// * [`IndexType64Mut`] for the mutable access -/// -/// to the `IndexType64` data. -/// -/// [`IndexType64Ref`]: struct.IndexType64Ref.html -/// [`IndexType64Mut`]: struct.IndexType64Mut.html -#[derive(Clone, Debug)] -pub struct IndexType64 {} +#[repr(transparent)] +pub struct IndexType64 { + data: [u8; 8], +} -/// Read-only access to [`IndexType64`]. -/// -/// [`IndexType64`]: struct.IndexType64.html -#[derive(Clone, Copy)] -pub struct IndexType64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl IndexType64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } } -impl<'a> flatdata::Struct<'a> for IndexType64 -{ +impl flatdata::Struct for IndexType64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } + const SCHEMA: &'static str = schema::structs::INDEX_TYPE64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = true; - - type Item = IndexType64Ref<'a>; - - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } - } - - type ItemMut = IndexType64Mut<'a>; - - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } - } } -impl<'a> IndexType64Ref<'a> { +impl IndexType64 { /// First element of the range [`range`]. /// /// [`range`]: #method.range #[inline] pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } #[inline] pub fn range(&self) -> std::ops::Range { - let start = flatdata_read_bytes!(u64, self.data, 0, 64); - let end = flatdata_read_bytes!(u64, self.data, 0 + 8 * 8, 64); + let start = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); + let end = flatdata_read_bytes!(u64, self.data.as_ptr(), 0 + 8 * 8, 64); start..end } } -impl<'a> std::fmt::Debug for IndexType64Ref<'a> { +impl std::fmt::Debug for IndexType64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("IndexType64") .field("value", &self.value()) @@ -1112,67 +994,40 @@ impl<'a> std::fmt::Debug for IndexType64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for IndexType64Ref<'a> { +impl std::cmp::PartialEq for IndexType64 { #[inline] fn eq(&self, other: &Self) -> bool { self.value() == other.value() } } -impl<'a> flatdata::Ref for IndexType64Ref<'a> {} - -/// Mutable access to [`IndexType64`]. -/// -/// [`IndexType64`]: struct.IndexType64.html -pub struct IndexType64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> IndexType64Mut<'a> { +impl IndexType64 { /// First element of the range [`range`]. /// /// [`range`]: struct.IndexType64Ref.html#method.range #[inline] - pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_value(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &IndexType64Ref) { + pub fn fill_from(&mut self, other: &IndexType64) { self.set_value(other.value()); } } -impl<'a> std::fmt::Debug for IndexType64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - IndexType64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for IndexType64Mut<'a> {} - -impl<'a> flatdata::IndexStruct<'a> for IndexType64 { +impl flatdata::IndexStruct for IndexType64 { #[inline] - fn range(data: Self::Item) -> std::ops::Range { - let range = data.range(); + fn range(&self) -> std::ops::Range { + let range = self.range(); range.start as usize..range.end as usize } #[inline] - fn set_index(mut data: Self::ItemMut, value: usize) { - data.set_value(value as u64); + fn set_index(&mut self, value: usize) { + self.set_value(value as u64); } } diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/namespaces.rs b/flatdata-generator/tests/generators/rust_expectations/archives/namespaces.rs index cb916065..9b4bfa9a 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/namespaces.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/namespaces.rs @@ -35,67 +35,93 @@ archive X "#; } } +}#[repr(transparent)] +#[derive(Clone)] +pub struct S { + data: [u8; 8], } -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`SRef`] for the read-only access, and -/// * [`SMut`] for the mutable access -/// -/// to the `S` data. -/// -/// [`SRef`]: struct.SRef.html -/// [`SMut`]: struct.SMut.html -#[derive(Clone, Debug)] -pub struct S {} -/// Read-only access to [`S`]. -/// -/// [`S`]: struct.S.html -#[derive(Clone, Copy)] -pub struct SRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl S { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } } -impl<'a> flatdata::Struct<'a> for S -{ +impl flatdata::Struct for S { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } + const SCHEMA: &'static str = schema::structs::S; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = SRef<'a>; +impl S { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = SMut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for S { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for S {} -impl<'a> SRef<'a> { +impl S { #[inline] pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for SRef<'a> { +impl std::fmt::Debug for S { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("S") .field("x", &self.x()) @@ -103,79 +129,43 @@ impl<'a> std::fmt::Debug for SRef<'a> { } } -impl<'a> std::cmp::PartialEq for SRef<'a> { +impl std::cmp::PartialEq for S { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() } } -impl<'a> flatdata::Ref for SRef<'a> {} - -/// Mutable access to [`S`]. -/// -/// [`S`]: struct.S.html -pub struct SMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> SMut<'a> { +impl S { #[inline] - pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &SRef) { + pub fn fill_from(&mut self, other: &S) { self.set_x(other.x()); } } -impl<'a> std::fmt::Debug for SMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - SRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for SMut<'a> {} - #[derive(Clone)] pub struct X { _storage: ::std::rc::Rc, - payload: flatdata::MemoryDescriptor, + payload : flatdata::RawData<'static>, } impl X { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] pub fn payload(&self) -> flatdata::RawData { - flatdata::RawData::new(unsafe {self.payload.as_bytes()}) + self.payload } } @@ -195,9 +185,16 @@ impl flatdata::Archive for X { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let payload = Self::read_resource(&*storage, "payload", schema::x::resources::PAYLOAD)?; + let resource = extend(storage.read("payload", schema::x::resources::PAYLOAD)); + let payload = resource.map(|x| flatdata::RawData::new(x))?; Ok(Self { _storage: storage, @@ -239,6 +236,7 @@ impl flatdata::ArchiveBuilder for XBuilder { } +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod m { @@ -277,67 +275,93 @@ archive X "#; } } +}#[repr(transparent)] +#[derive(Clone)] +pub struct S { + data: [u8; 8], } -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`SRef`] for the read-only access, and -/// * [`SMut`] for the mutable access -/// -/// to the `S` data. -/// -/// [`SRef`]: struct.SRef.html -/// [`SMut`]: struct.SMut.html -#[derive(Clone, Debug)] -pub struct S {} -/// Read-only access to [`S`]. -/// -/// [`S`]: struct.S.html -#[derive(Clone, Copy)] -pub struct SRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl S { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } } -impl<'a> flatdata::Struct<'a> for S -{ +impl flatdata::Struct for S { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } + const SCHEMA: &'static str = schema::structs::S; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = SRef<'a>; +impl S { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = SMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for S { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for S {} -impl<'a> SRef<'a> { +impl S { #[inline] pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for SRef<'a> { +impl std::fmt::Debug for S { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("S") .field("x", &self.x()) @@ -345,79 +369,43 @@ impl<'a> std::fmt::Debug for SRef<'a> { } } -impl<'a> std::cmp::PartialEq for SRef<'a> { +impl std::cmp::PartialEq for S { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() } } -impl<'a> flatdata::Ref for SRef<'a> {} - -/// Mutable access to [`S`]. -/// -/// [`S`]: struct.S.html -pub struct SMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> SMut<'a> { +impl S { #[inline] - pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &SRef) { + pub fn fill_from(&mut self, other: &S) { self.set_x(other.x()); } } -impl<'a> std::fmt::Debug for SMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - SRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for SMut<'a> {} - #[derive(Clone)] pub struct X { _storage: ::std::rc::Rc, - payload: flatdata::MemoryDescriptor, + payload : flatdata::RawData<'static>, } impl X { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] pub fn payload(&self) -> flatdata::RawData { - flatdata::RawData::new(unsafe {self.payload.as_bytes()}) + self.payload } } @@ -437,9 +425,16 @@ impl flatdata::Archive for X { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let payload = Self::read_resource(&*storage, "payload", schema::x::resources::PAYLOAD)?; + let resource = extend(storage.read("payload", schema::x::resources::PAYLOAD)); + let payload = resource.map(|x| flatdata::RawData::new(x))?; Ok(Self { _storage: storage, @@ -481,6 +476,7 @@ impl flatdata::ArchiveBuilder for XBuilder { } +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod a { @@ -596,7 +592,7 @@ archive A #[derive(Clone, PartialEq)] pub enum MultiRef<'a> { #[allow(missing_docs)] - S(>::Item),} + S(&'a super::n::S),} impl<'a> ::std::fmt::Debug for MultiRef<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -610,7 +606,7 @@ impl<'a> flatdata::VariadicRef for MultiRef<'a> { #[inline] fn size_in_bytes(&self) -> usize { match *self { - MultiRef::S(_) => >::SIZE_IN_BYTES, + MultiRef::S(_) => ::SIZE_IN_BYTES, } } } @@ -630,14 +626,13 @@ impl<'a> MultiBuilder<'a> { /// /// [`S`]: struct.S.html #[inline] - pub fn add_s<'b>(&'b mut self) -> >::ItemMut { + pub fn add_s<'b>(&'b mut self) -> &'b mut super::n::S { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 0; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 0; + let slice = &mut self.data[1 + old_len..]; + super::n::S::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::S from slice") } } @@ -662,16 +657,18 @@ impl<'a> MultiBuilder<'a> { #[derive(Clone)] pub struct Multi {} -impl<'a> flatdata::VariadicStruct<'a> for Multi { +impl flatdata::VariadicIndex for Multi { type Index = super::_builtin::multivector::IndexType32; +} +impl<'a> flatdata::VariadicStruct<'a> for Multi { type Item = MultiRef<'a>; #[inline] fn create(index: flatdata::TypeIndex, data: &'a [u8]) -> Self::Item { match index { - 0 => MultiRef::S(>::create(data)), + 0 => MultiRef::S(super::n::S::from_bytes_slice(&data).expect("Corrupted data")), _ => panic!("invalid type index {} for variadic type MultiRef", index), } } @@ -688,50 +685,35 @@ impl<'a> flatdata::VariadicStruct<'a> for Multi { #[derive(Clone)] pub struct A { _storage: ::std::rc::Rc, - single: flatdata::MemoryDescriptor, - list: flatdata::MemoryDescriptor, - multi: (flatdata::MemoryDescriptor, flatdata::MemoryDescriptor), - inner: super::n::X, + single : &'static super::n::S, + list : &'static [super::m::S], + multi : flatdata::MultiArrayView<'static, Multi>, + inner : super::n::X +, } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn single(&self) -> ::Item - { - ::create(&unsafe {self.single.as_bytes()}) + pub fn single(&self) -> &super::n::S { + self.single } #[inline] - pub fn list(&self) -> flatdata::ArrayView - { - flatdata::ArrayView::new(&unsafe {self.list.as_bytes()}) + pub fn list(&self) -> &[super::m::S] { + self.list } #[inline] - pub fn multi(&self) -> flatdata::MultiArrayView - { - flatdata::MultiArrayView::new( - flatdata::ArrayView::new(&unsafe {self.multi.0.as_bytes()}), - &unsafe {self.multi.1.as_bytes()}, - ) + pub fn multi(&self) -> &flatdata::MultiArrayView { + &self.multi } #[inline] - pub fn inner(&self) -> &super::n::X - { + pub fn inner(&self) -> &super::n::X { &self.inner } @@ -755,14 +737,33 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let single = Self::read_resource(&*storage, "single", schema::a::resources::SINGLE)?; - let list = Self::read_resource(&*storage, "list", schema::a::resources::LIST)?; + let resource = extend(storage.read("single", schema::a::resources::SINGLE)); + let single = resource.map(|x| super::n::S::from_bytes_slice(x))??; + let resource = extend(storage.read("list", schema::a::resources::LIST)); + let list = resource.map(|x| <&[super::m::S]>::from_bytes(x))??; let multi = { let index_schema = &format!("index({})", schema::a::resources::MULTI); - let index = Self::read_resource(&*storage, "multi_index", &index_schema)?; - let data = Self::read_resource(&*storage, "multi", schema::a::resources::MULTI)?; (index, data) + let index = extend(storage.read("multi_index", &index_schema)); + let data = extend(storage.read("multi", schema::a::resources::MULTI)); + let result = match (index, data) { + (Ok(index), Ok(data)) => { + Ok(flatdata::MultiArrayView::new( + <&[super::_builtin::multivector::IndexType32]>::from_bytes(index)?, + data + )) + } + (Ok(_), Err(x)) | (Err(x), Ok(_)) => {return Err(x);} + (Err(x), Err(_)) => Err(x), + }; + result? }; let inner = super::n::X::open(storage.subdir("inner"))?; @@ -789,10 +790,9 @@ impl ABuilder { /// Stores [`single`] in the archive. /// /// [`single`]: struct.A.html#method.single - pub fn set_single(&self, resource: ::Item) -> ::std::io::Result<()> { - let data = unsafe { - ::std::slice::from_raw_parts(resource.data, ::SIZE_IN_BYTES) - }; + /// Stores [`single`] in the archive. + pub fn set_single(&self, resource: &super::n::S) -> ::std::io::Result<()> { + let data = resource.as_bytes(); self.storage.write("single", schema::a::resources::SINGLE, data) } @@ -800,8 +800,9 @@ impl ABuilder { /// Stores [`list`] in the archive. /// /// [`list`]: struct.A.html#method.list - pub fn set_list(&self, vector: &flatdata::ArrayView) -> ::std::io::Result<()> { - self.storage.write("list", schema::a::resources::LIST, vector.as_ref()) + pub fn set_list(&self, vector: &[super::m::S]) -> ::std::io::Result<()> { + use flatdata::SliceExt; + self.storage.write("list", schema::a::resources::LIST, vector.as_bytes()) } /// Opens [`list`] in the archive for buffered writing. @@ -856,9 +857,11 @@ impl flatdata::ArchiveBuilder for ABuilder { } +#[cfg_attr(rustfmt, rustfmt_skip)] #[doc(hidden)] pub mod _builtin { +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod multivector { @@ -869,77 +872,50 @@ pub const INDEX_TYPE32: &str = r#""#; } } - /// Builtin type to for MultiVector index -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`IndexType32Ref`] for the read-only access, and -/// * [`IndexType32Mut`] for the mutable access -/// -/// to the `IndexType32` data. -/// -/// [`IndexType32Ref`]: struct.IndexType32Ref.html -/// [`IndexType32Mut`]: struct.IndexType32Mut.html -#[derive(Clone, Debug)] -pub struct IndexType32 {} +#[repr(transparent)] +pub struct IndexType32 { + data: [u8; 4], +} -/// Read-only access to [`IndexType32`]. -/// -/// [`IndexType32`]: struct.IndexType32.html -#[derive(Clone, Copy)] -pub struct IndexType32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl IndexType32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } } -impl<'a> flatdata::Struct<'a> for IndexType32 -{ +impl flatdata::Struct for IndexType32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } + const SCHEMA: &'static str = schema::structs::INDEX_TYPE32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = true; - - type Item = IndexType32Ref<'a>; - - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } - } - - type ItemMut = IndexType32Mut<'a>; - - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } - } } -impl<'a> IndexType32Ref<'a> { +impl IndexType32 { /// First element of the range [`range`]. /// /// [`range`]: #method.range #[inline] pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 32); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } #[inline] pub fn range(&self) -> std::ops::Range { - let start = flatdata_read_bytes!(u64, self.data, 0, 32); - let end = flatdata_read_bytes!(u64, self.data, 0 + 4 * 8, 32); + let start = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 32); + let end = flatdata_read_bytes!(u64, self.data.as_ptr(), 0 + 4 * 8, 32); start..end } } -impl<'a> std::fmt::Debug for IndexType32Ref<'a> { +impl std::fmt::Debug for IndexType32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("IndexType32") .field("value", &self.value()) @@ -947,67 +923,40 @@ impl<'a> std::fmt::Debug for IndexType32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for IndexType32Ref<'a> { +impl std::cmp::PartialEq for IndexType32 { #[inline] fn eq(&self, other: &Self) -> bool { self.value() == other.value() } } -impl<'a> flatdata::Ref for IndexType32Ref<'a> {} - -/// Mutable access to [`IndexType32`]. -/// -/// [`IndexType32`]: struct.IndexType32.html -pub struct IndexType32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> IndexType32Mut<'a> { +impl IndexType32 { /// First element of the range [`range`]. /// /// [`range`]: struct.IndexType32Ref.html#method.range #[inline] - pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_value(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 32) + flatdata_write_bytes!(u64; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &IndexType32Ref) { + pub fn fill_from(&mut self, other: &IndexType32) { self.set_value(other.value()); } } -impl<'a> std::fmt::Debug for IndexType32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - IndexType32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for IndexType32Mut<'a> {} - -impl<'a> flatdata::IndexStruct<'a> for IndexType32 { +impl flatdata::IndexStruct for IndexType32 { #[inline] - fn range(data: Self::Item) -> std::ops::Range { - let range = data.range(); + fn range(&self) -> std::ops::Range { + let range = self.range(); range.start as usize..range.end as usize } #[inline] - fn set_index(mut data: Self::ItemMut, value: usize) { - data.set_value(value as u64); + fn set_index(&mut self, value: usize) { + self.set_value(value as u64); } } diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/ranges.rs b/flatdata-generator/tests/generators/rust_expectations/archives/ranges.rs index 1aabe837..f9f5d070 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/ranges.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/ranges.rs @@ -1,56 +1,30 @@ -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`SRef`] for the read-only access, and -/// * [`SMut`] for the mutable access -/// -/// to the `S` data. -/// -/// [`SRef`]: struct.SRef.html -/// [`SMut`]: struct.SMut.html -#[derive(Clone, Debug)] -pub struct S {} +#[repr(transparent)] +pub struct S { + data: [u8; 10], +} -/// Read-only access to [`S`]. -/// -/// [`S`]: struct.S.html -#[derive(Clone, Copy)] -pub struct SRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl S { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 10]} + } } -impl<'a> flatdata::Struct<'a> for S -{ +impl flatdata::Struct for S { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 10]} + } + const SCHEMA: &'static str = schema::structs::S; const SIZE_IN_BYTES: usize = 10; const IS_OVERLAPPING_WITH_NEXT : bool = true; - - type Item = SRef<'a>; - - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } - } - - type ItemMut = SMut<'a>; - - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } - } } -impl<'a> SRef<'a> { +impl S { #[inline] pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } @@ -59,20 +33,20 @@ impl<'a> SRef<'a> { /// [`y_range`]: #method.y_range #[inline] pub fn first_y(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 64, 14); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 64, 14); unsafe { std::mem::transmute::(value) } } #[inline] pub fn y_range(&self) -> std::ops::Range { - let start = flatdata_read_bytes!(u32, self.data, 64, 14); - let end = flatdata_read_bytes!(u32, self.data, 64 + 10 * 8, 14); + let start = flatdata_read_bytes!(u32, self.data.as_ptr(), 64, 14); + let end = flatdata_read_bytes!(u32, self.data.as_ptr(), 64 + 10 * 8, 14); start..end } } -impl<'a> std::fmt::Debug for SRef<'a> { +impl std::fmt::Debug for S { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("S") .field("x", &self.x()) @@ -81,99 +55,53 @@ impl<'a> std::fmt::Debug for SRef<'a> { } } -impl<'a> std::cmp::PartialEq for SRef<'a> { +impl std::cmp::PartialEq for S { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() && self.first_y() == other.first_y() } } -impl<'a> flatdata::Ref for SRef<'a> {} - -/// Mutable access to [`S`]. -/// -/// [`S`]: struct.S.html -pub struct SMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> SMut<'a> { +impl S { #[inline] - pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 10) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// First element of the range [`y_range`]. /// /// [`y_range`]: struct.SRef.html#method.y_range #[inline] - pub fn first_y(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 64, 14); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_first_y(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 10) - }; - flatdata_write_bytes!(u32; value, buffer, 64, 14) + flatdata_write_bytes!(u32; value, self.data, 64, 14) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &SRef) { + pub fn fill_from(&mut self, other: &S) { self.set_x(other.x()); self.set_first_y(other.first_y()); } } -impl<'a> std::fmt::Debug for SMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - SRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for SMut<'a> {} - #[derive(Clone)] pub struct A { _storage: ::std::rc::Rc, - data: flatdata::MemoryDescriptor, + data : &'static [super::n::S], } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn data(&self) -> flatdata::ArrayView - { - flatdata::ArrayView::new(&unsafe {self.data.as_bytes()}) + pub fn data(&self) -> &[super::n::S] { + self.data } } @@ -193,9 +121,16 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let data = Self::read_resource(&*storage, "data", schema::a::resources::DATA)?; + let resource = extend(storage.read("data", schema::a::resources::DATA)); + let data = resource.map(|x| <&[super::n::S]>::from_bytes(x))??; Ok(Self { _storage: storage, @@ -217,8 +152,9 @@ impl ABuilder { /// Stores [`data`] in the archive. /// /// [`data`]: struct.A.html#method.data - pub fn set_data(&self, vector: &flatdata::ArrayView) -> ::std::io::Result<()> { - self.storage.write("data", schema::a::resources::DATA, vector.as_ref()) + pub fn set_data(&self, vector: &[super::n::S]) -> ::std::io::Result<()> { + use flatdata::SliceExt; + self.storage.write("data", schema::a::resources::DATA, vector.as_bytes()) } /// Opens [`data`] in the archive for buffered writing. diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/raw_data.rs b/flatdata-generator/tests/generators/rust_expectations/archives/raw_data.rs index e7af8797..e7a99110 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/raw_data.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/raw_data.rs @@ -1,32 +1,23 @@ #[derive(Clone)] pub struct A { _storage: ::std::rc::Rc, - data: flatdata::MemoryDescriptor, - optional_data: Option, + data : flatdata::RawData<'static>, + optional_data : Option>, } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] pub fn data(&self) -> flatdata::RawData { - flatdata::RawData::new(unsafe {self.data.as_bytes()}) + self.data } #[inline] pub fn optional_data(&self) -> Option { - self.optional_data.as_ref().map(|mem_desc| flatdata::RawData::new({unsafe {mem_desc.as_bytes()} })) + self.optional_data } } @@ -47,10 +38,18 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let data = Self::read_resource(&*storage, "data", schema::a::resources::DATA)?; - let optional_data = Self::read_resource(&*storage, "optional_data", schema::a::resources::OPTIONAL_DATA).ok(); + let resource = extend(storage.read("data", schema::a::resources::DATA)); + let data = resource.map(|x| flatdata::RawData::new(x))?; + let resource = extend(storage.read("optional_data", schema::a::resources::OPTIONAL_DATA)); + let optional_data = resource.map(|x| flatdata::RawData::new(x)).ok(); Ok(Self { _storage: storage, diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/references.rs b/flatdata-generator/tests/generators/rust_expectations/archives/references.rs index 4b058e17..830f842c 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/references.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/references.rs @@ -1,50 +1,90 @@ -#[derive(Clone, Debug)] -pub struct S {} +#[repr(transparent)] +#[derive(Clone)] +pub struct S { + data: [u8; 4], +} -/// Read-only access to [`S`]. -/// -/// [`S`]: struct.S.html -#[derive(Clone, Copy)] -pub struct SRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl S { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } } -impl<'a> flatdata::Struct<'a> for S -{ +impl flatdata::Struct for S { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } + const SCHEMA: &'static str = schema::structs::S; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = SRef<'a>; +impl S { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = SMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for S { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for S {} -impl<'a> SRef<'a> { +impl S { #[inline] pub fn x(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for SRef<'a> { +impl std::fmt::Debug for S { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("S") .field("x", &self.x()) @@ -52,114 +92,113 @@ impl<'a> std::fmt::Debug for SRef<'a> { } } -impl<'a> std::cmp::PartialEq for SRef<'a> { +impl std::cmp::PartialEq for S { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() } } -impl<'a> flatdata::Ref for SRef<'a> {} - -/// Mutable access to [`S`]. -/// -/// [`S`]: struct.S.html -pub struct SMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> SMut<'a> { +impl S { #[inline] - pub fn x(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 32) + flatdata_write_bytes!(u32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &SRef) { + pub fn fill_from(&mut self, other: &S) { self.set_x(other.x()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct R { + data: [u8; 4], +} -impl<'a> std::fmt::Debug for SMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - SRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) +impl R { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} } } -impl<'a> flatdata::RefMut for SMut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`RRef`] for the read-only access, and -/// * [`RMut`] for the mutable access -/// -/// to the `R` data. -/// -/// [`RRef`]: struct.RRef.html -/// [`RMut`]: struct.RMut.html -#[derive(Clone, Debug)] -pub struct R {} - -/// Read-only access to [`R`]. -/// -/// [`R`]: struct.R.html -#[derive(Clone, Copy)] -pub struct RRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} +impl flatdata::Struct for R { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> flatdata::Struct<'a> for R -{ const SCHEMA: &'static str = schema::structs::R; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = RRef<'a>; +impl R { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since R is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = RMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since R is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for R { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for R {} -impl<'a> RRef<'a> { +impl R { #[inline] pub fn ref_(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for RRef<'a> { +impl std::fmt::Debug for R { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("R") .field("ref_", &self.ref_()) @@ -167,54 +206,27 @@ impl<'a> std::fmt::Debug for RRef<'a> { } } -impl<'a> std::cmp::PartialEq for RRef<'a> { +impl std::cmp::PartialEq for R { #[inline] fn eq(&self, other: &Self) -> bool { self.ref_() == other.ref_() } } -impl<'a> flatdata::Ref for RRef<'a> {} - -/// Mutable access to [`R`]. -/// -/// [`R`]: struct.R.html -pub struct RMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> RMut<'a> { +impl R { #[inline] - pub fn ref_(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_ref_(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 32) + flatdata_write_bytes!(u32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &RRef) { + pub fn fill_from(&mut self, other: &R) { self.set_ref_(other.ref_()); } } -impl<'a> std::fmt::Debug for RMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - RRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for RMut<'a> {} - /// Enum for read-only heterogeneous access to elements in a /// bucket of the [`multilist`] resource. @@ -223,7 +235,7 @@ impl<'a> flatdata::RefMut for RMut<'a> {} #[derive(Clone, PartialEq)] pub enum MultilistRef<'a> { #[allow(missing_docs)] - S(>::Item),} + S(&'a super::n::S),} impl<'a> ::std::fmt::Debug for MultilistRef<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -237,7 +249,7 @@ impl<'a> flatdata::VariadicRef for MultilistRef<'a> { #[inline] fn size_in_bytes(&self) -> usize { match *self { - MultilistRef::S(_) => >::SIZE_IN_BYTES, + MultilistRef::S(_) => ::SIZE_IN_BYTES, } } } @@ -257,14 +269,13 @@ impl<'a> MultilistBuilder<'a> { /// /// [`S`]: struct.S.html #[inline] - pub fn add_s<'b>(&'b mut self) -> >::ItemMut { + pub fn add_s<'b>(&'b mut self) -> &'b mut super::n::S { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 0; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 0; + let slice = &mut self.data[1 + old_len..]; + super::n::S::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::S from slice") } } @@ -289,16 +300,18 @@ impl<'a> MultilistBuilder<'a> { #[derive(Clone)] pub struct Multilist {} -impl<'a> flatdata::VariadicStruct<'a> for Multilist { +impl flatdata::VariadicIndex for Multilist { type Index = super::_builtin::multivector::IndexType32; +} +impl<'a> flatdata::VariadicStruct<'a> for Multilist { type Item = MultilistRef<'a>; #[inline] fn create(index: flatdata::TypeIndex, data: &'a [u8]) -> Self::Item { match index { - 0 => MultilistRef::S(>::create(data)), + 0 => MultilistRef::S(super::n::S::from_bytes_slice(&data).expect("Corrupted data")), _ => panic!("invalid type index {} for variadic type MultilistRef", index), } } @@ -318,7 +331,7 @@ impl<'a> flatdata::VariadicStruct<'a> for Multilist { #[derive(Clone, PartialEq)] pub enum MultirefsRef<'a> { #[allow(missing_docs)] - R(>::Item),} + R(&'a super::n::R),} impl<'a> ::std::fmt::Debug for MultirefsRef<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -332,7 +345,7 @@ impl<'a> flatdata::VariadicRef for MultirefsRef<'a> { #[inline] fn size_in_bytes(&self) -> usize { match *self { - MultirefsRef::R(_) => >::SIZE_IN_BYTES, + MultirefsRef::R(_) => ::SIZE_IN_BYTES, } } } @@ -352,14 +365,13 @@ impl<'a> MultirefsBuilder<'a> { /// /// [`R`]: struct.R.html #[inline] - pub fn add_r<'b>(&'b mut self) -> >::ItemMut { + pub fn add_r<'b>(&'b mut self) -> &'b mut super::n::R { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - flatdata::PADDING_SIZE] = 0; - >::create_mut( - &mut self.data[1 + old_len - flatdata::PADDING_SIZE..] - ) + self.data[old_len] = 0; + let slice = &mut self.data[1 + old_len..]; + super::n::R::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::n::R from slice") } } @@ -384,16 +396,18 @@ impl<'a> MultirefsBuilder<'a> { #[derive(Clone)] pub struct Multirefs {} -impl<'a> flatdata::VariadicStruct<'a> for Multirefs { +impl flatdata::VariadicIndex for Multirefs { type Index = super::_builtin::multivector::IndexType32; +} +impl<'a> flatdata::VariadicStruct<'a> for Multirefs { type Item = MultirefsRef<'a>; #[inline] fn create(index: flatdata::TypeIndex, data: &'a [u8]) -> Self::Item { match index { - 0 => MultirefsRef::R(>::create(data)), + 0 => MultirefsRef::R(super::n::R::from_bytes_slice(&data).expect("Corrupted data")), _ => panic!("invalid type index {} for variadic type MultirefsRef", index), } } @@ -410,61 +424,41 @@ impl<'a> flatdata::VariadicStruct<'a> for Multirefs { #[derive(Clone)] pub struct A { _storage: ::std::rc::Rc, - list1: flatdata::MemoryDescriptor, - list2: flatdata::MemoryDescriptor, - multilist: (flatdata::MemoryDescriptor, flatdata::MemoryDescriptor), - refs: flatdata::MemoryDescriptor, - multirefs: (flatdata::MemoryDescriptor, flatdata::MemoryDescriptor), + list1 : &'static [super::n::S], + list2 : &'static [super::n::S], + multilist : flatdata::MultiArrayView<'static, Multilist>, + refs : &'static [super::n::R], + multirefs : flatdata::MultiArrayView<'static, Multirefs>, } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn list1(&self) -> flatdata::ArrayView - { - flatdata::ArrayView::new(&unsafe {self.list1.as_bytes()}) + pub fn list1(&self) -> &[super::n::S] { + self.list1 } #[inline] - pub fn list2(&self) -> flatdata::ArrayView - { - flatdata::ArrayView::new(&unsafe {self.list2.as_bytes()}) + pub fn list2(&self) -> &[super::n::S] { + self.list2 } #[inline] - pub fn multilist(&self) -> flatdata::MultiArrayView - { - flatdata::MultiArrayView::new( - flatdata::ArrayView::new(&unsafe {self.multilist.0.as_bytes()}), - &unsafe {self.multilist.1.as_bytes()}, - ) + pub fn multilist(&self) -> &flatdata::MultiArrayView { + &self.multilist } #[inline] - pub fn refs(&self) -> flatdata::ArrayView - { - flatdata::ArrayView::new(&unsafe {self.refs.as_bytes()}) + pub fn refs(&self) -> &[super::n::R] { + self.refs } #[inline] - pub fn multirefs(&self) -> flatdata::MultiArrayView - { - flatdata::MultiArrayView::new( - flatdata::ArrayView::new(&unsafe {self.multirefs.0.as_bytes()}), - &unsafe {self.multirefs.1.as_bytes()}, - ) + pub fn multirefs(&self) -> &flatdata::MultiArrayView { + &self.multirefs } } @@ -488,20 +482,51 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let list1 = Self::read_resource(&*storage, "list1", schema::a::resources::LIST1)?; - let list2 = Self::read_resource(&*storage, "list2", schema::a::resources::LIST2)?; + let resource = extend(storage.read("list1", schema::a::resources::LIST1)); + let list1 = resource.map(|x| <&[super::n::S]>::from_bytes(x))??; + let resource = extend(storage.read("list2", schema::a::resources::LIST2)); + let list2 = resource.map(|x| <&[super::n::S]>::from_bytes(x))??; let multilist = { let index_schema = &format!("index({})", schema::a::resources::MULTILIST); - let index = Self::read_resource(&*storage, "multilist_index", &index_schema)?; - let data = Self::read_resource(&*storage, "multilist", schema::a::resources::MULTILIST)?; (index, data) + let index = extend(storage.read("multilist_index", &index_schema)); + let data = extend(storage.read("multilist", schema::a::resources::MULTILIST)); + let result = match (index, data) { + (Ok(index), Ok(data)) => { + Ok(flatdata::MultiArrayView::new( + <&[super::_builtin::multivector::IndexType32]>::from_bytes(index)?, + data + )) + } + (Ok(_), Err(x)) | (Err(x), Ok(_)) => {return Err(x);} + (Err(x), Err(_)) => Err(x), + }; + result? }; - let refs = Self::read_resource(&*storage, "refs", schema::a::resources::REFS)?; + let resource = extend(storage.read("refs", schema::a::resources::REFS)); + let refs = resource.map(|x| <&[super::n::R]>::from_bytes(x))??; let multirefs = { let index_schema = &format!("index({})", schema::a::resources::MULTIREFS); - let index = Self::read_resource(&*storage, "multirefs_index", &index_schema)?; - let data = Self::read_resource(&*storage, "multirefs", schema::a::resources::MULTIREFS)?; (index, data) + let index = extend(storage.read("multirefs_index", &index_schema)); + let data = extend(storage.read("multirefs", schema::a::resources::MULTIREFS)); + let result = match (index, data) { + (Ok(index), Ok(data)) => { + Ok(flatdata::MultiArrayView::new( + <&[super::_builtin::multivector::IndexType32]>::from_bytes(index)?, + data + )) + } + (Ok(_), Err(x)) | (Err(x), Ok(_)) => {return Err(x);} + (Err(x), Err(_)) => Err(x), + }; + result? }; Ok(Self { @@ -528,8 +553,9 @@ impl ABuilder { /// Stores [`list1`] in the archive. /// /// [`list1`]: struct.A.html#method.list1 - pub fn set_list1(&self, vector: &flatdata::ArrayView) -> ::std::io::Result<()> { - self.storage.write("list1", schema::a::resources::LIST1, vector.as_ref()) + pub fn set_list1(&self, vector: &[super::n::S]) -> ::std::io::Result<()> { + use flatdata::SliceExt; + self.storage.write("list1", schema::a::resources::LIST1, vector.as_bytes()) } /// Opens [`list1`] in the archive for buffered writing. @@ -549,8 +575,9 @@ impl ABuilder { /// Stores [`list2`] in the archive. /// /// [`list2`]: struct.A.html#method.list2 - pub fn set_list2(&self, vector: &flatdata::ArrayView) -> ::std::io::Result<()> { - self.storage.write("list2", schema::a::resources::LIST2, vector.as_ref()) + pub fn set_list2(&self, vector: &[super::n::S]) -> ::std::io::Result<()> { + use flatdata::SliceExt; + self.storage.write("list2", schema::a::resources::LIST2, vector.as_bytes()) } /// Opens [`list2`] in the archive for buffered writing. @@ -583,8 +610,9 @@ impl ABuilder { /// Stores [`refs`] in the archive. /// /// [`refs`]: struct.A.html#method.refs - pub fn set_refs(&self, vector: &flatdata::ArrayView) -> ::std::io::Result<()> { - self.storage.write("refs", schema::a::resources::REFS, vector.as_ref()) + pub fn set_refs(&self, vector: &[super::n::R]) -> ::std::io::Result<()> { + use flatdata::SliceExt; + self.storage.write("refs", schema::a::resources::REFS, vector.as_bytes()) } /// Opens [`refs`] in the archive for buffered writing. @@ -629,9 +657,11 @@ impl flatdata::ArchiveBuilder for ABuilder { } +#[cfg_attr(rustfmt, rustfmt_skip)] #[doc(hidden)] pub mod _builtin { +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod multivector { @@ -642,77 +672,50 @@ pub const INDEX_TYPE32: &str = r#""#; } } - /// Builtin type to for MultiVector index -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`IndexType32Ref`] for the read-only access, and -/// * [`IndexType32Mut`] for the mutable access -/// -/// to the `IndexType32` data. -/// -/// [`IndexType32Ref`]: struct.IndexType32Ref.html -/// [`IndexType32Mut`]: struct.IndexType32Mut.html -#[derive(Clone, Debug)] -pub struct IndexType32 {} +#[repr(transparent)] +pub struct IndexType32 { + data: [u8; 4], +} -/// Read-only access to [`IndexType32`]. -/// -/// [`IndexType32`]: struct.IndexType32.html -#[derive(Clone, Copy)] -pub struct IndexType32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl IndexType32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } } -impl<'a> flatdata::Struct<'a> for IndexType32 -{ +impl flatdata::Struct for IndexType32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } + const SCHEMA: &'static str = schema::structs::INDEX_TYPE32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = true; - - type Item = IndexType32Ref<'a>; - - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } - } - - type ItemMut = IndexType32Mut<'a>; - - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } - } } -impl<'a> IndexType32Ref<'a> { +impl IndexType32 { /// First element of the range [`range`]. /// /// [`range`]: #method.range #[inline] pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 32); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } #[inline] pub fn range(&self) -> std::ops::Range { - let start = flatdata_read_bytes!(u64, self.data, 0, 32); - let end = flatdata_read_bytes!(u64, self.data, 0 + 4 * 8, 32); + let start = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 32); + let end = flatdata_read_bytes!(u64, self.data.as_ptr(), 0 + 4 * 8, 32); start..end } } -impl<'a> std::fmt::Debug for IndexType32Ref<'a> { +impl std::fmt::Debug for IndexType32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("IndexType32") .field("value", &self.value()) @@ -720,66 +723,39 @@ impl<'a> std::fmt::Debug for IndexType32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for IndexType32Ref<'a> { +impl std::cmp::PartialEq for IndexType32 { #[inline] fn eq(&self, other: &Self) -> bool { self.value() == other.value() } } -impl<'a> flatdata::Ref for IndexType32Ref<'a> {} - -/// Mutable access to [`IndexType32`]. -/// -/// [`IndexType32`]: struct.IndexType32.html -pub struct IndexType32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> IndexType32Mut<'a> { +impl IndexType32 { /// First element of the range [`range`]. /// /// [`range`]: struct.IndexType32Ref.html#method.range #[inline] - pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_value(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 32) + flatdata_write_bytes!(u64; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &IndexType32Ref) { + pub fn fill_from(&mut self, other: &IndexType32) { self.set_value(other.value()); } } -impl<'a> std::fmt::Debug for IndexType32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - IndexType32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for IndexType32Mut<'a> {} - -impl<'a> flatdata::IndexStruct<'a> for IndexType32 { +impl flatdata::IndexStruct for IndexType32 { #[inline] - fn range(data: Self::Item) -> std::ops::Range { - let range = data.range(); + fn range(&self) -> std::ops::Range { + let range = self.range(); range.start as usize..range.end as usize } #[inline] - fn set_index(mut data: Self::ItemMut, value: usize) { - data.set_value(value as u64); + fn set_index(&mut self, value: usize) { + self.set_value(value as u64); } } \ No newline at end of file diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/struct.rs b/flatdata-generator/tests/generators/rust_expectations/archives/struct.rs index e186fdbf..c9b50ed9 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/struct.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/struct.rs @@ -1,63 +1,90 @@ -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`SRef`] for the read-only access, and -/// * [`SMut`] for the mutable access -/// -/// to the `S` data. -/// -/// [`SRef`]: struct.SRef.html -/// [`SMut`]: struct.SMut.html -#[derive(Clone, Debug)] -pub struct S {} +#[repr(transparent)] +#[derive(Clone)] +pub struct S { + data: [u8; 8], +} -/// Read-only access to [`S`]. -/// -/// [`S`]: struct.S.html -#[derive(Clone, Copy)] -pub struct SRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl S { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } } -impl<'a> flatdata::Struct<'a> for S -{ +impl flatdata::Struct for S { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } + const SCHEMA: &'static str = schema::structs::S; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = SRef<'a>; +impl S { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = SMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for S { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for S {} -impl<'a> SRef<'a> { +impl S { #[inline] pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for SRef<'a> { +impl std::fmt::Debug for S { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("S") .field("x", &self.x()) @@ -65,87 +92,49 @@ impl<'a> std::fmt::Debug for SRef<'a> { } } -impl<'a> std::cmp::PartialEq for SRef<'a> { +impl std::cmp::PartialEq for S { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() } } -impl<'a> flatdata::Ref for SRef<'a> {} - -/// Mutable access to [`S`]. -/// -/// [`S`]: struct.S.html -pub struct SMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> SMut<'a> { +impl S { #[inline] - pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &SRef) { + pub fn fill_from(&mut self, other: &S) { self.set_x(other.x()); } } -impl<'a> std::fmt::Debug for SMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - SRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for SMut<'a> {} - #[derive(Clone)] pub struct A { _storage: ::std::rc::Rc, - data: flatdata::MemoryDescriptor, - optional_data: Option, + data : &'static super::n::S, + optional_data : Option<&'static super::n::S>, } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn data(&self) -> ::Item - { - ::create(&unsafe {self.data.as_bytes()}) + pub fn data(&self) -> &super::n::S { + self.data } #[inline] - pub fn optional_data(&self) -> Option<::Item> - { - self.optional_data.as_ref().map(|mem_desc| {::create(&unsafe {mem_desc.as_bytes()})}) + pub fn optional_data(&self) -> Option<&super::n::S> { + self.optional_data } } @@ -166,10 +155,18 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let data = Self::read_resource(&*storage, "data", schema::a::resources::DATA)?; - let optional_data = Self::read_resource(&*storage, "optional_data", schema::a::resources::OPTIONAL_DATA).ok(); + let resource = extend(storage.read("data", schema::a::resources::DATA)); + let data = resource.map(|x| super::n::S::from_bytes_slice(x))??; + let resource = extend(storage.read("optional_data", schema::a::resources::OPTIONAL_DATA)); + let optional_data = resource.map(|x| super::n::S::from_bytes_slice(x)).ok().transpose()?; Ok(Self { _storage: storage, @@ -192,10 +189,9 @@ impl ABuilder { /// Stores [`data`] in the archive. /// /// [`data`]: struct.A.html#method.data - pub fn set_data(&self, resource: ::Item) -> ::std::io::Result<()> { - let data = unsafe { - ::std::slice::from_raw_parts(resource.data, ::SIZE_IN_BYTES) - }; + /// Stores [`data`] in the archive. + pub fn set_data(&self, resource: &super::n::S) -> ::std::io::Result<()> { + let data = resource.as_bytes(); self.storage.write("data", schema::a::resources::DATA, data) } @@ -203,10 +199,9 @@ impl ABuilder { /// Stores [`optional_data`] in the archive. /// /// [`optional_data`]: struct.A.html#method.optional_data - pub fn set_optional_data(&self, resource: ::Item) -> ::std::io::Result<()> { - let data = unsafe { - ::std::slice::from_raw_parts(resource.data, ::SIZE_IN_BYTES) - }; + /// Stores [`optional_data`] in the archive. + pub fn set_optional_data(&self, resource: &super::n::S) -> ::std::io::Result<()> { + let data = resource.as_bytes(); self.storage.write("optional_data", schema::a::resources::OPTIONAL_DATA, data) } diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/subarchive.rs b/flatdata-generator/tests/generators/rust_expectations/archives/subarchive.rs index 8e9302ff..31ac11ba 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/subarchive.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/subarchive.rs @@ -1,26 +1,17 @@ #[derive(Clone)] pub struct X { _storage: ::std::rc::Rc, - payload: flatdata::MemoryDescriptor, + payload : flatdata::RawData<'static>, } impl X { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] pub fn payload(&self) -> flatdata::RawData { - flatdata::RawData::new(unsafe {self.payload.as_bytes()}) + self.payload } } @@ -40,9 +31,16 @@ impl flatdata::Archive for X { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let payload = Self::read_resource(&*storage, "payload", schema::x::resources::PAYLOAD)?; + let resource = extend(storage.read("payload", schema::x::resources::PAYLOAD)); + let payload = resource.map(|x| flatdata::RawData::new(x))?; Ok(Self { _storage: storage, @@ -88,33 +86,24 @@ impl flatdata::ArchiveBuilder for XBuilder { #[derive(Clone)] pub struct A { _storage: ::std::rc::Rc, - data: super::n::X, - optional_data: Option, + data : super::n::X +, + optional_data : Option, } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn data(&self) -> &super::n::X - { + pub fn data(&self) -> &super::n::X { &self.data } #[inline] - pub fn optional_data(&self) -> Option<&super::n::X> - { + pub fn optional_data(&self) -> Option<&super::n::X> { self.optional_data.as_ref() } @@ -136,6 +125,12 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; let data = super::n::X::open(storage.subdir("data"))?; @@ -190,4 +185,4 @@ impl flatdata::ArchiveBuilder for ABuilder { flatdata::create_archive::(&storage)?; Ok(Self { storage }) } -} +} \ No newline at end of file diff --git a/flatdata-generator/tests/generators/rust_expectations/archives/vector.rs b/flatdata-generator/tests/generators/rust_expectations/archives/vector.rs index 3635ac6a..fe958c7b 100644 --- a/flatdata-generator/tests/generators/rust_expectations/archives/vector.rs +++ b/flatdata-generator/tests/generators/rust_expectations/archives/vector.rs @@ -1,62 +1,90 @@ -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`SRef`] for the read-only access, and -/// * [`SMut`] for the mutable access -/// -/// to the `S` data. -/// -/// [`SRef`]: struct.SRef.html -/// [`SMut`]: struct.SMut.html -#[derive(Clone, Debug)] -pub struct S {} +#[repr(transparent)] +#[derive(Clone)] +pub struct S { + data: [u8; 8], +} -/// Read-only access to [`S`]. -/// -/// [`S`]: struct.S.html -#[derive(Clone, Copy)] -pub struct SRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl S { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } } -impl<'a> flatdata::Struct<'a> for S -{ +impl flatdata::Struct for S { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } + const SCHEMA: &'static str = schema::structs::S; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = SRef<'a>; +impl S { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = SMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since S is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for S { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for S {} -impl<'a> SRef<'a> { +impl S { #[inline] pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for SRef<'a> { +impl std::fmt::Debug for S { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("S") .field("x", &self.x()) @@ -64,87 +92,49 @@ impl<'a> std::fmt::Debug for SRef<'a> { } } -impl<'a> std::cmp::PartialEq for SRef<'a> { +impl std::cmp::PartialEq for S { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() } } -impl<'a> flatdata::Ref for SRef<'a> {} - -/// Mutable access to [`S`]. -/// -/// [`S`]: struct.S.html -pub struct SMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> SMut<'a> { +impl S { #[inline] - pub fn x(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &SRef) { + pub fn fill_from(&mut self, other: &S) { self.set_x(other.x()); } } -impl<'a> std::fmt::Debug for SMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - SRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for SMut<'a> {} - #[derive(Clone)] pub struct A { _storage: ::std::rc::Rc, - data: flatdata::MemoryDescriptor, - optional_data: Option, + data : &'static [super::n::S], + optional_data : Option<&'static [super::n::S]>, } impl A { - fn read_resource( - storage: &dyn flatdata::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| flatdata::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn data(&self) -> flatdata::ArrayView - { - flatdata::ArrayView::new(&unsafe {self.data.as_bytes()}) + pub fn data(&self) -> &[super::n::S] { + self.data } #[inline] - pub fn optional_data(&self) -> Option> - { - self.optional_data.as_ref().map(|x|flatdata::ArrayView::new(unsafe {x.as_bytes()})) + pub fn optional_data(&self) -> Option<&[super::n::S]> { + self.optional_data } } @@ -165,10 +155,18 @@ impl flatdata::Archive for A { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use flatdata::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], flatdata::ResourceStorageError>| -> Result<&'static [u8], flatdata::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let data = Self::read_resource(&*storage, "data", schema::a::resources::DATA)?; - let optional_data = Self::read_resource(&*storage, "optional_data", schema::a::resources::OPTIONAL_DATA).ok(); + let resource = extend(storage.read("data", schema::a::resources::DATA)); + let data = resource.map(|x| <&[super::n::S]>::from_bytes(x))??; + let resource = extend(storage.read("optional_data", schema::a::resources::OPTIONAL_DATA)); + let optional_data = resource.map(|x| <&[super::n::S]>::from_bytes(x)).ok().transpose()?; Ok(Self { _storage: storage, @@ -191,8 +189,9 @@ impl ABuilder { /// Stores [`data`] in the archive. /// /// [`data`]: struct.A.html#method.data - pub fn set_data(&self, vector: &flatdata::ArrayView) -> ::std::io::Result<()> { - self.storage.write("data", schema::a::resources::DATA, vector.as_ref()) + pub fn set_data(&self, vector: &[super::n::S]) -> ::std::io::Result<()> { + use flatdata::SliceExt; + self.storage.write("data", schema::a::resources::DATA, vector.as_bytes()) } /// Opens [`data`] in the archive for buffered writing. @@ -212,8 +211,9 @@ impl ABuilder { /// Stores [`optional_data`] in the archive. /// /// [`optional_data`]: struct.A.html#method.optional_data - pub fn set_optional_data(&self, vector: &flatdata::ArrayView) -> ::std::io::Result<()> { - self.storage.write("optional_data", schema::a::resources::OPTIONAL_DATA, vector.as_ref()) + pub fn set_optional_data(&self, vector: &[super::n::S]) -> ::std::io::Result<()> { + use flatdata::SliceExt; + self.storage.write("optional_data", schema::a::resources::OPTIONAL_DATA, vector.as_bytes()) } /// Opens [`optional_data`] in the archive for buffered writing. @@ -242,3 +242,5 @@ impl flatdata::ArchiveBuilder for ABuilder { Ok(Self { storage }) } } + +} diff --git a/flatdata-generator/tests/generators/rust_expectations/constants/namespaces.rs b/flatdata-generator/tests/generators/rust_expectations/constants/namespaces.rs index c070606d..23d8c548 100644 --- a/flatdata-generator/tests/generators/rust_expectations/constants/namespaces.rs +++ b/flatdata-generator/tests/generators/rust_expectations/constants/namespaces.rs @@ -9,6 +9,7 @@ pub mod structs { pub const FOO: i8 = 0; } +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod m { diff --git a/flatdata-generator/tests/generators/rust_expectations/enums/default_width.rs b/flatdata-generator/tests/generators/rust_expectations/enums/default_width.rs index 49ace5cc..37cad4b0 100644 --- a/flatdata-generator/tests/generators/rust_expectations/enums/default_width.rs +++ b/flatdata-generator/tests/generators/rust_expectations/enums/default_width.rs @@ -1,62 +1,90 @@ -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumI8Ref`] for the read-only access, and -/// * [`StructEnumI8Mut`] for the mutable access -/// -/// to the `StructEnumI8` data. -/// -/// [`StructEnumI8Ref`]: struct.StructEnumI8Ref.html -/// [`StructEnumI8Mut`]: struct.StructEnumI8Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumI8 {} - -/// Read-only access to [`StructEnumI8`]. -/// -/// [`StructEnumI8`]: struct.StructEnumI8.html -#[derive(Clone, Copy)] -pub struct StructEnumI8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumI8 -{ +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumI8 { + data: [u8; 1], +} + +impl StructEnumI8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumI8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } + const SCHEMA: &'static str = schema::structs::STRUCT_ENUMI8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumI8Ref<'a>; +impl StructEnumI8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumI8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumI8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumI8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumI8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumI8 {} -impl<'a> StructEnumI8Ref<'a> { +impl StructEnumI8 { #[inline] pub fn f(&self) -> super::n::EnumI8 { - let value = flatdata_read_bytes!(i8, self.data, 0, 8); + let value = flatdata_read_bytes!(i8, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumI8Ref<'a> { +impl std::fmt::Debug for StructEnumI8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumI8") .field("f", &self.f()) @@ -64,114 +92,113 @@ impl<'a> std::fmt::Debug for StructEnumI8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumI8Ref<'a> { +impl std::cmp::PartialEq for StructEnumI8 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumI8Ref<'a> {} - -/// Mutable access to [`StructEnumI8`]. -/// -/// [`StructEnumI8`]: struct.StructEnumI8.html -pub struct StructEnumI8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumI8Mut<'a> { +impl StructEnumI8 { #[inline] - pub fn f(&self) -> super::n::EnumI8 { - let value = flatdata_read_bytes!(i8, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumI8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(i8; value, buffer, 0, 8) + flatdata_write_bytes!(i8; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumI8Ref) { + pub fn fill_from(&mut self, other: &StructEnumI8) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumU8 { + data: [u8; 1], +} + +impl StructEnumU8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumU8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for StructEnumI8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumI8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumI8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumU8Ref`] for the read-only access, and -/// * [`StructEnumU8Mut`] for the mutable access -/// -/// to the `StructEnumU8` data. -/// -/// [`StructEnumU8Ref`]: struct.StructEnumU8Ref.html -/// [`StructEnumU8Mut`]: struct.StructEnumU8Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumU8 {} - -/// Read-only access to [`StructEnumU8`]. -/// -/// [`StructEnumU8`]: struct.StructEnumU8.html -#[derive(Clone, Copy)] -pub struct StructEnumU8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumU8 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMU8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumU8Ref<'a>; +impl StructEnumU8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumU8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumU8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumU8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumU8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumU8 {} -impl<'a> StructEnumU8Ref<'a> { +impl StructEnumU8 { #[inline] pub fn f(&self) -> super::n::EnumU8 { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); + let value = flatdata_read_bytes!(u8, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumU8Ref<'a> { +impl std::fmt::Debug for StructEnumU8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumU8") .field("f", &self.f()) @@ -179,114 +206,113 @@ impl<'a> std::fmt::Debug for StructEnumU8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumU8Ref<'a> { +impl std::cmp::PartialEq for StructEnumU8 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumU8Ref<'a> {} - -/// Mutable access to [`StructEnumU8`]. -/// -/// [`StructEnumU8`]: struct.StructEnumU8.html -pub struct StructEnumU8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumU8Mut<'a> { +impl StructEnumU8 { #[inline] - pub fn f(&self) -> super::n::EnumU8 { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumU8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u8; value, buffer, 0, 8) + flatdata_write_bytes!(u8; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumU8Ref) { + pub fn fill_from(&mut self, other: &StructEnumU8) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumI16 { + data: [u8; 2], +} + +impl StructEnumI16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } +} + +impl flatdata::Struct for StructEnumI16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> std::fmt::Debug for StructEnumU8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumU8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumU8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumI16Ref`] for the read-only access, and -/// * [`StructEnumI16Mut`] for the mutable access -/// -/// to the `StructEnumI16` data. -/// -/// [`StructEnumI16Ref`]: struct.StructEnumI16Ref.html -/// [`StructEnumI16Mut`]: struct.StructEnumI16Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumI16 {} - -/// Read-only access to [`StructEnumI16`]. -/// -/// [`StructEnumI16`]: struct.StructEnumI16.html -#[derive(Clone, Copy)] -pub struct StructEnumI16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumI16 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMI16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} + +impl StructEnumI16 { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - type Item = StructEnumI16Ref<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since StructEnumI16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since StructEnumI16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumI16Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for StructEnumI16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumI16 {} -impl<'a> StructEnumI16Ref<'a> { +impl StructEnumI16 { #[inline] pub fn f(&self) -> super::n::EnumI16 { - let value = flatdata_read_bytes!(i16, self.data, 0, 16); + let value = flatdata_read_bytes!(i16, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumI16Ref<'a> { +impl std::fmt::Debug for StructEnumI16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumI16") .field("f", &self.f()) @@ -294,114 +320,113 @@ impl<'a> std::fmt::Debug for StructEnumI16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumI16Ref<'a> { +impl std::cmp::PartialEq for StructEnumI16 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumI16Ref<'a> {} - -/// Mutable access to [`StructEnumI16`]. -/// -/// [`StructEnumI16`]: struct.StructEnumI16.html -pub struct StructEnumI16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumI16Mut<'a> { +impl StructEnumI16 { #[inline] - pub fn f(&self) -> super::n::EnumI16 { - let value = flatdata_read_bytes!(i16, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumI16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(i16; value, buffer, 0, 16) + flatdata_write_bytes!(i16; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumI16Ref) { + pub fn fill_from(&mut self, other: &StructEnumI16) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumU16 { + data: [u8; 2], +} + +impl StructEnumU16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } +} + +impl flatdata::Struct for StructEnumU16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> std::fmt::Debug for StructEnumI16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumI16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumI16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumU16Ref`] for the read-only access, and -/// * [`StructEnumU16Mut`] for the mutable access -/// -/// to the `StructEnumU16` data. -/// -/// [`StructEnumU16Ref`]: struct.StructEnumU16Ref.html -/// [`StructEnumU16Mut`]: struct.StructEnumU16Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumU16 {} - -/// Read-only access to [`StructEnumU16`]. -/// -/// [`StructEnumU16`]: struct.StructEnumU16.html -#[derive(Clone, Copy)] -pub struct StructEnumU16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumU16 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMU16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumU16Ref<'a>; +impl StructEnumU16 { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since StructEnumU16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumU16Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since StructEnumU16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for StructEnumU16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumU16 {} -impl<'a> StructEnumU16Ref<'a> { +impl StructEnumU16 { #[inline] pub fn f(&self) -> super::n::EnumU16 { - let value = flatdata_read_bytes!(u16, self.data, 0, 16); + let value = flatdata_read_bytes!(u16, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumU16Ref<'a> { +impl std::fmt::Debug for StructEnumU16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumU16") .field("f", &self.f()) @@ -409,114 +434,113 @@ impl<'a> std::fmt::Debug for StructEnumU16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumU16Ref<'a> { +impl std::cmp::PartialEq for StructEnumU16 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumU16Ref<'a> {} - -/// Mutable access to [`StructEnumU16`]. -/// -/// [`StructEnumU16`]: struct.StructEnumU16.html -pub struct StructEnumU16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumU16Mut<'a> { +impl StructEnumU16 { #[inline] - pub fn f(&self) -> super::n::EnumU16 { - let value = flatdata_read_bytes!(u16, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumU16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u16; value, buffer, 0, 16) + flatdata_write_bytes!(u16; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumU16Ref) { + pub fn fill_from(&mut self, other: &StructEnumU16) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumI32 { + data: [u8; 4], +} + +impl StructEnumI32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for StructEnumI32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> std::fmt::Debug for StructEnumU16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumU16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumU16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumI32Ref`] for the read-only access, and -/// * [`StructEnumI32Mut`] for the mutable access -/// -/// to the `StructEnumI32` data. -/// -/// [`StructEnumI32Ref`]: struct.StructEnumI32Ref.html -/// [`StructEnumI32Mut`]: struct.StructEnumI32Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumI32 {} - -/// Read-only access to [`StructEnumI32`]. -/// -/// [`StructEnumI32`]: struct.StructEnumI32.html -#[derive(Clone, Copy)] -pub struct StructEnumI32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumI32 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMI32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumI32Ref<'a>; +impl StructEnumI32 { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since StructEnumI32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumI32Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since StructEnumI32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for StructEnumI32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumI32 {} -impl<'a> StructEnumI32Ref<'a> { +impl StructEnumI32 { #[inline] pub fn f(&self) -> super::n::EnumI32 { - let value = flatdata_read_bytes!(i32, self.data, 0, 32); + let value = flatdata_read_bytes!(i32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumI32Ref<'a> { +impl std::fmt::Debug for StructEnumI32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumI32") .field("f", &self.f()) @@ -524,114 +548,113 @@ impl<'a> std::fmt::Debug for StructEnumI32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumI32Ref<'a> { +impl std::cmp::PartialEq for StructEnumI32 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumI32Ref<'a> {} - -/// Mutable access to [`StructEnumI32`]. -/// -/// [`StructEnumI32`]: struct.StructEnumI32.html -pub struct StructEnumI32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumI32Mut<'a> { +impl StructEnumI32 { #[inline] - pub fn f(&self) -> super::n::EnumI32 { - let value = flatdata_read_bytes!(i32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumI32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(i32; value, buffer, 0, 32) + flatdata_write_bytes!(i32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumI32Ref) { + pub fn fill_from(&mut self, other: &StructEnumI32) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumU32 { + data: [u8; 4], +} + +impl StructEnumU32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for StructEnumU32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> std::fmt::Debug for StructEnumI32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumI32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumI32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumU32Ref`] for the read-only access, and -/// * [`StructEnumU32Mut`] for the mutable access -/// -/// to the `StructEnumU32` data. -/// -/// [`StructEnumU32Ref`]: struct.StructEnumU32Ref.html -/// [`StructEnumU32Mut`]: struct.StructEnumU32Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumU32 {} - -/// Read-only access to [`StructEnumU32`]. -/// -/// [`StructEnumU32`]: struct.StructEnumU32.html -#[derive(Clone, Copy)] -pub struct StructEnumU32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumU32 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMU32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumU32Ref<'a>; +impl StructEnumU32 { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since StructEnumU32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since StructEnumU32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumU32Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for StructEnumU32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumU32 {} -impl<'a> StructEnumU32Ref<'a> { +impl StructEnumU32 { #[inline] pub fn f(&self) -> super::n::EnumU32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumU32Ref<'a> { +impl std::fmt::Debug for StructEnumU32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumU32") .field("f", &self.f()) @@ -639,114 +662,113 @@ impl<'a> std::fmt::Debug for StructEnumU32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumU32Ref<'a> { +impl std::cmp::PartialEq for StructEnumU32 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumU32Ref<'a> {} - -/// Mutable access to [`StructEnumU32`]. -/// -/// [`StructEnumU32`]: struct.StructEnumU32.html -pub struct StructEnumU32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumU32Mut<'a> { +impl StructEnumU32 { #[inline] - pub fn f(&self) -> super::n::EnumU32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumU32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 32) + flatdata_write_bytes!(u32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumU32Ref) { + pub fn fill_from(&mut self, other: &StructEnumU32) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumI64 { + data: [u8; 8], +} + +impl StructEnumI64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } +} + +impl flatdata::Struct for StructEnumI64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> std::fmt::Debug for StructEnumU32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumU32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumU32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumI64Ref`] for the read-only access, and -/// * [`StructEnumI64Mut`] for the mutable access -/// -/// to the `StructEnumI64` data. -/// -/// [`StructEnumI64Ref`]: struct.StructEnumI64Ref.html -/// [`StructEnumI64Mut`]: struct.StructEnumI64Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumI64 {} - -/// Read-only access to [`StructEnumI64`]. -/// -/// [`StructEnumI64`]: struct.StructEnumI64.html -#[derive(Clone, Copy)] -pub struct StructEnumI64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumI64 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMI64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumI64Ref<'a>; +impl StructEnumI64 { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since StructEnumI64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since StructEnumI64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumI64Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for StructEnumI64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumI64 {} -impl<'a> StructEnumI64Ref<'a> { +impl StructEnumI64 { #[inline] pub fn f(&self) -> super::n::EnumI64 { - let value = flatdata_read_bytes!(i64, self.data, 0, 64); + let value = flatdata_read_bytes!(i64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumI64Ref<'a> { +impl std::fmt::Debug for StructEnumI64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumI64") .field("f", &self.f()) @@ -754,114 +776,113 @@ impl<'a> std::fmt::Debug for StructEnumI64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumI64Ref<'a> { +impl std::cmp::PartialEq for StructEnumI64 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumI64Ref<'a> {} - -/// Mutable access to [`StructEnumI64`]. -/// -/// [`StructEnumI64`]: struct.StructEnumI64.html -pub struct StructEnumI64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumI64Mut<'a> { +impl StructEnumI64 { #[inline] - pub fn f(&self) -> super::n::EnumI64 { - let value = flatdata_read_bytes!(i64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumI64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(i64; value, buffer, 0, 64) + flatdata_write_bytes!(i64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumI64Ref) { + pub fn fill_from(&mut self, other: &StructEnumI64) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumU64 { + data: [u8; 8], +} + +impl StructEnumU64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } +} + +impl flatdata::Struct for StructEnumU64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> std::fmt::Debug for StructEnumI64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumI64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumI64Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumU64Ref`] for the read-only access, and -/// * [`StructEnumU64Mut`] for the mutable access -/// -/// to the `StructEnumU64` data. -/// -/// [`StructEnumU64Ref`]: struct.StructEnumU64Ref.html -/// [`StructEnumU64Mut`]: struct.StructEnumU64Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumU64 {} - -/// Read-only access to [`StructEnumU64`]. -/// -/// [`StructEnumU64`]: struct.StructEnumU64.html -#[derive(Clone, Copy)] -pub struct StructEnumU64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumU64 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMU64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumU64Ref<'a>; +impl StructEnumU64 { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since StructEnumU64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumU64Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since StructEnumU64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for StructEnumU64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumU64 {} -impl<'a> StructEnumU64Ref<'a> { +impl StructEnumU64 { #[inline] pub fn f(&self) -> super::n::EnumU64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumU64Ref<'a> { +impl std::fmt::Debug for StructEnumU64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumU64") .field("f", &self.f()) @@ -869,53 +890,26 @@ impl<'a> std::fmt::Debug for StructEnumU64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumU64Ref<'a> { +impl std::cmp::PartialEq for StructEnumU64 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumU64Ref<'a> {} - -/// Mutable access to [`StructEnumU64`]. -/// -/// [`StructEnumU64`]: struct.StructEnumU64.html -pub struct StructEnumU64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumU64Mut<'a> { +impl StructEnumU64 { #[inline] - pub fn f(&self) -> super::n::EnumU64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumU64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumU64Ref) { + pub fn fill_from(&mut self, other: &StructEnumU64) { self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for StructEnumU64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumU64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumU64Mut<'a> {} #[derive(Debug, PartialEq, Eq)] #[repr(i8)] pub enum EnumI8 { diff --git a/flatdata-generator/tests/generators/rust_expectations/enums/namespaces.rs b/flatdata-generator/tests/generators/rust_expectations/enums/namespaces.rs index 69b488a8..5d61cb8c 100644 --- a/flatdata-generator/tests/generators/rust_expectations/enums/namespaces.rs +++ b/flatdata-generator/tests/generators/rust_expectations/enums/namespaces.rs @@ -9,6 +9,7 @@ impl flatdata::helper::Int for Bar { } } +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod b { @@ -28,6 +29,7 @@ impl flatdata::helper::Int for Bar { } } +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod n { @@ -51,67 +53,93 @@ struct Foo "#; } +}#[repr(transparent)] +#[derive(Clone)] +pub struct Foo { + data: [u8; 1], } -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`FooRef`] for the read-only access, and -/// * [`FooMut`] for the mutable access -/// -/// to the `Foo` data. -/// -/// [`FooRef`]: struct.FooRef.html -/// [`FooMut`]: struct.FooMut.html -#[derive(Clone, Debug)] -pub struct Foo {} - -/// Read-only access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -#[derive(Clone, Copy)] -pub struct FooRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for Foo -{ + +impl Foo { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for Foo { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } + const SCHEMA: &'static str = schema::structs::FOO; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = FooRef<'a>; +impl Foo { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = FooMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for Foo { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for Foo {} -impl<'a> FooRef<'a> { +impl Foo { #[inline] pub fn f(&self) -> super::a::Bar { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); + let value = flatdata_read_bytes!(u8, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for FooRef<'a> { +impl std::fmt::Debug for Foo { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("Foo") .field("f", &self.f()) @@ -119,55 +147,29 @@ impl<'a> std::fmt::Debug for FooRef<'a> { } } -impl<'a> std::cmp::PartialEq for FooRef<'a> { +impl std::cmp::PartialEq for Foo { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for FooRef<'a> {} - -/// Mutable access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -pub struct FooMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> FooMut<'a> { +impl Foo { #[inline] - pub fn f(&self) -> super::a::Bar { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::a::Bar) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u8; value, buffer, 0, 8) + flatdata_write_bytes!(u8; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &FooRef) { + pub fn fill_from(&mut self, other: &Foo) { self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for FooMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - FooRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for FooMut<'a> {} } +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod m { @@ -191,67 +193,93 @@ struct Foo "#; } +}#[repr(transparent)] +#[derive(Clone)] +pub struct Foo { + data: [u8; 1], } -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`FooRef`] for the read-only access, and -/// * [`FooMut`] for the mutable access -/// -/// to the `Foo` data. -/// -/// [`FooRef`]: struct.FooRef.html -/// [`FooMut`]: struct.FooMut.html -#[derive(Clone, Debug)] -pub struct Foo {} - -/// Read-only access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -#[derive(Clone, Copy)] -pub struct FooRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for Foo -{ + +impl Foo { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for Foo { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } + const SCHEMA: &'static str = schema::structs::FOO; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = FooRef<'a>; +impl Foo { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = FooMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for Foo { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for Foo {} -impl<'a> FooRef<'a> { +impl Foo { #[inline] pub fn f(&self) -> super::b::Bar { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); + let value = flatdata_read_bytes!(u8, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for FooRef<'a> { +impl std::fmt::Debug for Foo { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("Foo") .field("f", &self.f()) @@ -259,50 +287,24 @@ impl<'a> std::fmt::Debug for FooRef<'a> { } } -impl<'a> std::cmp::PartialEq for FooRef<'a> { +impl std::cmp::PartialEq for Foo { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for FooRef<'a> {} - -/// Mutable access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -pub struct FooMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> FooMut<'a> { +impl Foo { #[inline] - pub fn f(&self) -> super::b::Bar { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::b::Bar) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u8; value, buffer, 0, 8) + flatdata_write_bytes!(u8; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &FooRef) { + pub fn fill_from(&mut self, other: &Foo) { self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for FooMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - FooRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } } - -impl<'a> flatdata::RefMut for FooMut<'a> {} \ No newline at end of file diff --git a/flatdata-generator/tests/generators/rust_expectations/enums/structs.rs b/flatdata-generator/tests/generators/rust_expectations/enums/structs.rs index 1ebe6299..d976f795 100644 --- a/flatdata-generator/tests/generators/rust_expectations/enums/structs.rs +++ b/flatdata-generator/tests/generators/rust_expectations/enums/structs.rs @@ -1,63 +1,90 @@ -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumI8Ref`] for the read-only access, and -/// * [`StructEnumI8Mut`] for the mutable access -/// -/// to the `StructEnumI8` data. -/// -/// [`StructEnumI8Ref`]: struct.StructEnumI8Ref.html -/// [`StructEnumI8Mut`]: struct.StructEnumI8Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumI8 {} - -/// Read-only access to [`StructEnumI8`]. -/// -/// [`StructEnumI8`]: struct.StructEnumI8.html -#[derive(Clone, Copy)] -pub struct StructEnumI8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumI8 -{ +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumI8 { + data: [u8; 1], +} + +impl StructEnumI8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumI8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } + const SCHEMA: &'static str = schema::structs::STRUCT_ENUMI8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumI8Ref<'a>; +impl StructEnumI8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumI8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumI8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumI8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumI8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumI8 {} -impl<'a> StructEnumI8Ref<'a> { +impl StructEnumI8 { #[inline] pub fn f(&self) -> super::n::EnumI8 { - let value = flatdata_read_bytes!(i8, self.data, 0, 1); + let value = flatdata_read_bytes!(i8, self.data.as_ptr(), 0, 1); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumI8Ref<'a> { +impl std::fmt::Debug for StructEnumI8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumI8") .field("f", &self.f()) @@ -65,114 +92,113 @@ impl<'a> std::fmt::Debug for StructEnumI8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumI8Ref<'a> { +impl std::cmp::PartialEq for StructEnumI8 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumI8Ref<'a> {} - -/// Mutable access to [`StructEnumI8`]. -/// -/// [`StructEnumI8`]: struct.StructEnumI8.html -pub struct StructEnumI8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumI8Mut<'a> { +impl StructEnumI8 { #[inline] - pub fn f(&self) -> super::n::EnumI8 { - let value = flatdata_read_bytes!(i8, self.data, 0, 1); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumI8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(i8; value, buffer, 0, 1) + flatdata_write_bytes!(i8; value, self.data, 0, 1) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumI8Ref) { + pub fn fill_from(&mut self, other: &StructEnumI8) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumU8 { + data: [u8; 1], +} + +impl StructEnumU8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumU8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for StructEnumI8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumI8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumI8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumU8Ref`] for the read-only access, and -/// * [`StructEnumU8Mut`] for the mutable access -/// -/// to the `StructEnumU8` data. -/// -/// [`StructEnumU8Ref`]: struct.StructEnumU8Ref.html -/// [`StructEnumU8Mut`]: struct.StructEnumU8Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumU8 {} - -/// Read-only access to [`StructEnumU8`]. -/// -/// [`StructEnumU8`]: struct.StructEnumU8.html -#[derive(Clone, Copy)] -pub struct StructEnumU8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumU8 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMU8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumU8Ref<'a>; +impl StructEnumU8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumU8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumU8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumU8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumU8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumU8 {} -impl<'a> StructEnumU8Ref<'a> { +impl StructEnumU8 { #[inline] pub fn f(&self) -> super::n::EnumU8 { - let value = flatdata_read_bytes!(u8, self.data, 0, 1); + let value = flatdata_read_bytes!(u8, self.data.as_ptr(), 0, 1); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumU8Ref<'a> { +impl std::fmt::Debug for StructEnumU8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumU8") .field("f", &self.f()) @@ -180,114 +206,113 @@ impl<'a> std::fmt::Debug for StructEnumU8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumU8Ref<'a> { +impl std::cmp::PartialEq for StructEnumU8 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumU8Ref<'a> {} - -/// Mutable access to [`StructEnumU8`]. -/// -/// [`StructEnumU8`]: struct.StructEnumU8.html -pub struct StructEnumU8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumU8Mut<'a> { +impl StructEnumU8 { #[inline] - pub fn f(&self) -> super::n::EnumU8 { - let value = flatdata_read_bytes!(u8, self.data, 0, 1); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumU8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u8; value, buffer, 0, 1) + flatdata_write_bytes!(u8; value, self.data, 0, 1) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumU8Ref) { + pub fn fill_from(&mut self, other: &StructEnumU8) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumI16 { + data: [u8; 1], +} + +impl StructEnumI16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumI16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for StructEnumU8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumU8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumU8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumI16Ref`] for the read-only access, and -/// * [`StructEnumI16Mut`] for the mutable access -/// -/// to the `StructEnumI16` data. -/// -/// [`StructEnumI16Ref`]: struct.StructEnumI16Ref.html -/// [`StructEnumI16Mut`]: struct.StructEnumI16Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumI16 {} - -/// Read-only access to [`StructEnumI16`]. -/// -/// [`StructEnumI16`]: struct.StructEnumI16.html -#[derive(Clone, Copy)] -pub struct StructEnumI16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumI16 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMI16; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} + +impl StructEnumI16 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - type Item = StructEnumI16Ref<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumI16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumI16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumI16Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumI16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumI16 {} -impl<'a> StructEnumI16Ref<'a> { +impl StructEnumI16 { #[inline] pub fn f(&self) -> super::n::EnumI16 { - let value = flatdata_read_bytes!(i16, self.data, 0, 1); + let value = flatdata_read_bytes!(i16, self.data.as_ptr(), 0, 1); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumI16Ref<'a> { +impl std::fmt::Debug for StructEnumI16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumI16") .field("f", &self.f()) @@ -295,114 +320,113 @@ impl<'a> std::fmt::Debug for StructEnumI16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumI16Ref<'a> { +impl std::cmp::PartialEq for StructEnumI16 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumI16Ref<'a> {} - -/// Mutable access to [`StructEnumI16`]. -/// -/// [`StructEnumI16`]: struct.StructEnumI16.html -pub struct StructEnumI16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumI16Mut<'a> { +impl StructEnumI16 { #[inline] - pub fn f(&self) -> super::n::EnumI16 { - let value = flatdata_read_bytes!(i16, self.data, 0, 1); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumI16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(i16; value, buffer, 0, 1) + flatdata_write_bytes!(i16; value, self.data, 0, 1) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumI16Ref) { + pub fn fill_from(&mut self, other: &StructEnumI16) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumU16 { + data: [u8; 1], +} + +impl StructEnumU16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumU16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for StructEnumI16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumI16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumI16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumU16Ref`] for the read-only access, and -/// * [`StructEnumU16Mut`] for the mutable access -/// -/// to the `StructEnumU16` data. -/// -/// [`StructEnumU16Ref`]: struct.StructEnumU16Ref.html -/// [`StructEnumU16Mut`]: struct.StructEnumU16Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumU16 {} - -/// Read-only access to [`StructEnumU16`]. -/// -/// [`StructEnumU16`]: struct.StructEnumU16.html -#[derive(Clone, Copy)] -pub struct StructEnumU16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumU16 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMU16; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumU16Ref<'a>; +impl StructEnumU16 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumU16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumU16Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumU16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumU16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumU16 {} -impl<'a> StructEnumU16Ref<'a> { +impl StructEnumU16 { #[inline] pub fn f(&self) -> super::n::EnumU16 { - let value = flatdata_read_bytes!(u16, self.data, 0, 1); + let value = flatdata_read_bytes!(u16, self.data.as_ptr(), 0, 1); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumU16Ref<'a> { +impl std::fmt::Debug for StructEnumU16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumU16") .field("f", &self.f()) @@ -410,114 +434,113 @@ impl<'a> std::fmt::Debug for StructEnumU16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumU16Ref<'a> { +impl std::cmp::PartialEq for StructEnumU16 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumU16Ref<'a> {} - -/// Mutable access to [`StructEnumU16`]. -/// -/// [`StructEnumU16`]: struct.StructEnumU16.html -pub struct StructEnumU16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumU16Mut<'a> { +impl StructEnumU16 { #[inline] - pub fn f(&self) -> super::n::EnumU16 { - let value = flatdata_read_bytes!(u16, self.data, 0, 1); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumU16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u16; value, buffer, 0, 1) + flatdata_write_bytes!(u16; value, self.data, 0, 1) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumU16Ref) { + pub fn fill_from(&mut self, other: &StructEnumU16) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumI32 { + data: [u8; 1], +} + +impl StructEnumI32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumI32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for StructEnumU16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumU16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumU16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumI32Ref`] for the read-only access, and -/// * [`StructEnumI32Mut`] for the mutable access -/// -/// to the `StructEnumI32` data. -/// -/// [`StructEnumI32Ref`]: struct.StructEnumI32Ref.html -/// [`StructEnumI32Mut`]: struct.StructEnumI32Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumI32 {} - -/// Read-only access to [`StructEnumI32`]. -/// -/// [`StructEnumI32`]: struct.StructEnumI32.html -#[derive(Clone, Copy)] -pub struct StructEnumI32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumI32 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMI32; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumI32Ref<'a>; +impl StructEnumI32 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumI32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumI32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumI32Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumI32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumI32 {} -impl<'a> StructEnumI32Ref<'a> { +impl StructEnumI32 { #[inline] pub fn f(&self) -> super::n::EnumI32 { - let value = flatdata_read_bytes!(i32, self.data, 0, 1); + let value = flatdata_read_bytes!(i32, self.data.as_ptr(), 0, 1); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumI32Ref<'a> { +impl std::fmt::Debug for StructEnumI32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumI32") .field("f", &self.f()) @@ -525,114 +548,113 @@ impl<'a> std::fmt::Debug for StructEnumI32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumI32Ref<'a> { +impl std::cmp::PartialEq for StructEnumI32 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumI32Ref<'a> {} - -/// Mutable access to [`StructEnumI32`]. -/// -/// [`StructEnumI32`]: struct.StructEnumI32.html -pub struct StructEnumI32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumI32Mut<'a> { +impl StructEnumI32 { #[inline] - pub fn f(&self) -> super::n::EnumI32 { - let value = flatdata_read_bytes!(i32, self.data, 0, 1); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumI32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(i32; value, buffer, 0, 1) + flatdata_write_bytes!(i32; value, self.data, 0, 1) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumI32Ref) { + pub fn fill_from(&mut self, other: &StructEnumI32) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumU32 { + data: [u8; 1], +} + +impl StructEnumU32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumU32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for StructEnumI32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumI32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumI32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumU32Ref`] for the read-only access, and -/// * [`StructEnumU32Mut`] for the mutable access -/// -/// to the `StructEnumU32` data. -/// -/// [`StructEnumU32Ref`]: struct.StructEnumU32Ref.html -/// [`StructEnumU32Mut`]: struct.StructEnumU32Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumU32 {} - -/// Read-only access to [`StructEnumU32`]. -/// -/// [`StructEnumU32`]: struct.StructEnumU32.html -#[derive(Clone, Copy)] -pub struct StructEnumU32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumU32 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMU32; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumU32Ref<'a>; +impl StructEnumU32 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumU32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumU32Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumU32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumU32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumU32 {} -impl<'a> StructEnumU32Ref<'a> { +impl StructEnumU32 { #[inline] pub fn f(&self) -> super::n::EnumU32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 1); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 1); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumU32Ref<'a> { +impl std::fmt::Debug for StructEnumU32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumU32") .field("f", &self.f()) @@ -640,114 +662,113 @@ impl<'a> std::fmt::Debug for StructEnumU32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumU32Ref<'a> { +impl std::cmp::PartialEq for StructEnumU32 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumU32Ref<'a> {} - -/// Mutable access to [`StructEnumU32`]. -/// -/// [`StructEnumU32`]: struct.StructEnumU32.html -pub struct StructEnumU32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumU32Mut<'a> { +impl StructEnumU32 { #[inline] - pub fn f(&self) -> super::n::EnumU32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 1); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumU32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 1) + flatdata_write_bytes!(u32; value, self.data, 0, 1) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumU32Ref) { + pub fn fill_from(&mut self, other: &StructEnumU32) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumI64 { + data: [u8; 1], +} + +impl StructEnumI64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumI64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for StructEnumU32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumU32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumU32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumI64Ref`] for the read-only access, and -/// * [`StructEnumI64Mut`] for the mutable access -/// -/// to the `StructEnumI64` data. -/// -/// [`StructEnumI64Ref`]: struct.StructEnumI64Ref.html -/// [`StructEnumI64Mut`]: struct.StructEnumI64Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumI64 {} - -/// Read-only access to [`StructEnumI64`]. -/// -/// [`StructEnumI64`]: struct.StructEnumI64.html -#[derive(Clone, Copy)] -pub struct StructEnumI64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumI64 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMI64; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumI64Ref<'a>; +impl StructEnumI64 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumI64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumI64Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumI64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumI64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumI64 {} -impl<'a> StructEnumI64Ref<'a> { +impl StructEnumI64 { #[inline] pub fn f(&self) -> super::n::EnumI64 { - let value = flatdata_read_bytes!(i64, self.data, 0, 1); + let value = flatdata_read_bytes!(i64, self.data.as_ptr(), 0, 1); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumI64Ref<'a> { +impl std::fmt::Debug for StructEnumI64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumI64") .field("f", &self.f()) @@ -755,114 +776,113 @@ impl<'a> std::fmt::Debug for StructEnumI64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumI64Ref<'a> { +impl std::cmp::PartialEq for StructEnumI64 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumI64Ref<'a> {} - -/// Mutable access to [`StructEnumI64`]. -/// -/// [`StructEnumI64`]: struct.StructEnumI64.html -pub struct StructEnumI64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumI64Mut<'a> { +impl StructEnumI64 { #[inline] - pub fn f(&self) -> super::n::EnumI64 { - let value = flatdata_read_bytes!(i64, self.data, 0, 1); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumI64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(i64; value, buffer, 0, 1) + flatdata_write_bytes!(i64; value, self.data, 0, 1) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumI64Ref) { + pub fn fill_from(&mut self, other: &StructEnumI64) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct StructEnumU64 { + data: [u8; 1], +} + +impl StructEnumU64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for StructEnumU64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for StructEnumI64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumI64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumI64Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`StructEnumU64Ref`] for the read-only access, and -/// * [`StructEnumU64Mut`] for the mutable access -/// -/// to the `StructEnumU64` data. -/// -/// [`StructEnumU64Ref`]: struct.StructEnumU64Ref.html -/// [`StructEnumU64Mut`]: struct.StructEnumU64Mut.html -#[derive(Clone, Debug)] -pub struct StructEnumU64 {} - -/// Read-only access to [`StructEnumU64`]. -/// -/// [`StructEnumU64`]: struct.StructEnumU64.html -#[derive(Clone, Copy)] -pub struct StructEnumU64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for StructEnumU64 -{ const SCHEMA: &'static str = schema::structs::STRUCT_ENUMU64; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = StructEnumU64Ref<'a>; +impl StructEnumU64 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since StructEnumU64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = StructEnumU64Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since StructEnumU64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for StructEnumU64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for StructEnumU64 {} -impl<'a> StructEnumU64Ref<'a> { +impl StructEnumU64 { #[inline] pub fn f(&self) -> super::n::EnumU64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 1); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 1); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for StructEnumU64Ref<'a> { +impl std::fmt::Debug for StructEnumU64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("StructEnumU64") .field("f", &self.f()) @@ -870,53 +890,26 @@ impl<'a> std::fmt::Debug for StructEnumU64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for StructEnumU64Ref<'a> { +impl std::cmp::PartialEq for StructEnumU64 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for StructEnumU64Ref<'a> {} - -/// Mutable access to [`StructEnumU64`]. -/// -/// [`StructEnumU64`]: struct.StructEnumU64.html -pub struct StructEnumU64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> StructEnumU64Mut<'a> { +impl StructEnumU64 { #[inline] - pub fn f(&self) -> super::n::EnumU64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 1); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: super::n::EnumU64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 1) + flatdata_write_bytes!(u64; value, self.data, 0, 1) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &StructEnumU64Ref) { + pub fn fill_from(&mut self, other: &StructEnumU64) { self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for StructEnumU64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - StructEnumU64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for StructEnumU64Mut<'a> {} #[derive(Debug, PartialEq, Eq)] #[repr(i8)] pub enum EnumI8 { @@ -988,4 +981,5 @@ pub enum EnumU64 { impl flatdata::helper::Int for EnumU64 { const IS_SIGNED: bool = false; -} \ No newline at end of file +} +} diff --git a/flatdata-generator/tests/generators/rust_expectations/structs/comments.rs b/flatdata-generator/tests/generators/rust_expectations/structs/comments.rs index bcf5dba5..6e486372 100644 --- a/flatdata-generator/tests/generators/rust_expectations/structs/comments.rs +++ b/flatdata-generator/tests/generators/rust_expectations/structs/comments.rs @@ -1,72 +1,99 @@ // This is a comment about Foo -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`FooRef`] for the read-only access, and -/// * [`FooMut`] for the mutable access -/// -/// to the `Foo` data. -/// -/// [`FooRef`]: struct.FooRef.html -/// [`FooMut`]: struct.FooMut.html -#[derive(Clone, Debug)] -pub struct Foo {} - -/// Read-only access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -#[derive(Clone, Copy)] -pub struct FooRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +#[repr(transparent)] +#[derive(Clone)] +pub struct Foo { + data: [u8; 16], } -impl<'a> flatdata::Struct<'a> for Foo -{ +impl Foo { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 16]} + } +} + +impl flatdata::Struct for Foo { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 16]} + } + const SCHEMA: &'static str = schema::structs::FOO; const SIZE_IN_BYTES: usize = 16; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = FooRef<'a>; +impl Foo { + pub fn new( ) -> Self { + Self{data : [0; 16]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 16]) -> &Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = FooMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 16]) -> &mut Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 16 { + assert_eq!(data.len(), 16); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 16]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 16 { + assert_eq!(data.len(), 16); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 16]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 16] { + &self.data + } +} + +impl Default for Foo { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for Foo {} -impl<'a> FooRef<'a> { +impl Foo { // This is a comment about Foo.a #[inline] pub fn a(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } // This is a comment about Foo.b #[inline] pub fn b(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 64, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 64, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for FooRef<'a> { +impl std::fmt::Debug for Foo { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("Foo") .field("a", &self.a()) @@ -75,141 +102,131 @@ impl<'a> std::fmt::Debug for FooRef<'a> { } } -impl<'a> std::cmp::PartialEq for FooRef<'a> { +impl std::cmp::PartialEq for Foo { #[inline] fn eq(&self, other: &Self) -> bool { self.a() == other.a() && self.b() == other.b() } } -impl<'a> flatdata::Ref for FooRef<'a> {} - -/// Mutable access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -pub struct FooMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> FooMut<'a> { +impl Foo { // This is a comment about Foo.a #[inline] - pub fn a(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_a(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 16) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } // This is a comment about Foo.b #[inline] - pub fn b(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 64, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_b(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 16) - }; - flatdata_write_bytes!(u64; value, buffer, 64, 64) + flatdata_write_bytes!(u64; value, self.data, 64, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &FooRef) { + pub fn fill_from(&mut self, other: &Foo) { self.set_a(other.a()); self.set_b(other.b()); } } +/// This is a comment about Bar +#[repr(transparent)] +#[derive(Clone)] +pub struct Bar { + data: [u8; 16], +} -impl<'a> std::fmt::Debug for FooMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - FooRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) +impl Bar { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 16]} } } -impl<'a> flatdata::RefMut for FooMut<'a> {} - -/// This is a comment about Bar -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`BarRef`] for the read-only access, and -/// * [`BarMut`] for the mutable access -/// -/// to the `Bar` data. -/// -/// [`BarRef`]: struct.BarRef.html -/// [`BarMut`]: struct.BarMut.html -#[derive(Clone, Debug)] -pub struct Bar {} - -/// Read-only access to [`Bar`]. -/// -/// [`Bar`]: struct.Bar.html -#[derive(Clone, Copy)] -pub struct BarRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} +impl flatdata::Struct for Bar { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 16]} + } -impl<'a> flatdata::Struct<'a> for Bar -{ const SCHEMA: &'static str = schema::structs::BAR; const SIZE_IN_BYTES: usize = 16; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = BarRef<'a>; +impl Bar { + pub fn new( ) -> Self { + Self{data : [0; 16]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 16]) -> &Self { + // Safety: This is safe since Bar is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = BarMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 16]) -> &mut Self { + // Safety: This is safe since Bar is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 16 { + assert_eq!(data.len(), 16); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 16]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 16 { + assert_eq!(data.len(), 16); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 16]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 16] { + &self.data + } +} + +impl Default for Bar { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for Bar {} -impl<'a> BarRef<'a> { +impl Bar { /// This is a comment about Bar.a #[inline] pub fn a(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } /// This is a comment about Bar.b #[inline] pub fn b(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 64, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 64, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for BarRef<'a> { +impl std::fmt::Debug for Bar { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("Bar") .field("a", &self.a()) @@ -218,68 +235,33 @@ impl<'a> std::fmt::Debug for BarRef<'a> { } } -impl<'a> std::cmp::PartialEq for BarRef<'a> { +impl std::cmp::PartialEq for Bar { #[inline] fn eq(&self, other: &Self) -> bool { self.a() == other.a() && self.b() == other.b() } } -impl<'a> flatdata::Ref for BarRef<'a> {} - -/// Mutable access to [`Bar`]. -/// -/// [`Bar`]: struct.Bar.html -pub struct BarMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> BarMut<'a> { +impl Bar { /// This is a comment about Bar.a #[inline] - pub fn a(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_a(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 16) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// This is a comment about Bar.b #[inline] - pub fn b(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 64, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_b(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 16) - }; - flatdata_write_bytes!(u64; value, buffer, 64, 64) + flatdata_write_bytes!(u64; value, self.data, 64, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &BarRef) { + pub fn fill_from(&mut self, other: &Bar) { self.set_a(other.a()); self.set_b(other.b()); } } - -impl<'a> std::fmt::Debug for BarMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - BarRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } } - -impl<'a> flatdata::RefMut for BarMut<'a> {} \ No newline at end of file diff --git a/flatdata-generator/tests/generators/rust_expectations/structs/default_width.rs b/flatdata-generator/tests/generators/rust_expectations/structs/default_width.rs index ea6a08c7..37985d02 100644 --- a/flatdata-generator/tests/generators/rust_expectations/structs/default_width.rs +++ b/flatdata-generator/tests/generators/rust_expectations/structs/default_width.rs @@ -1,63 +1,90 @@ -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U8Ref`] for the read-only access, and -/// * [`U8Mut`] for the mutable access -/// -/// to the `U8` data. -/// -/// [`U8Ref`]: struct.U8Ref.html -/// [`U8Mut`]: struct.U8Mut.html -#[derive(Clone, Debug)] -pub struct U8 {} - -/// Read-only access to [`U8`]. -/// -/// [`U8`]: struct.U8.html -#[derive(Clone, Copy)] -pub struct U8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U8 -{ +#[repr(transparent)] +#[derive(Clone)] +pub struct U8 { + data: [u8; 1], +} + +impl U8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for U8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } + const SCHEMA: &'static str = schema::structs::U8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U8Ref<'a>; +impl U8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since U8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since U8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for U8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U8 {} -impl<'a> U8Ref<'a> { +impl U8 { #[inline] pub fn f(&self) -> u8 { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); + let value = flatdata_read_bytes!(u8, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U8Ref<'a> { +impl std::fmt::Debug for U8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U8") .field("f", &self.f()) @@ -65,114 +92,113 @@ impl<'a> std::fmt::Debug for U8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U8Ref<'a> { +impl std::cmp::PartialEq for U8 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for U8Ref<'a> {} - -/// Mutable access to [`U8`]. -/// -/// [`U8`]: struct.U8.html -pub struct U8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U8Mut<'a> { +impl U8 { #[inline] - pub fn f(&self) -> u8 { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u8; value, buffer, 0, 8) + flatdata_write_bytes!(u8; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U8Ref) { + pub fn fill_from(&mut self, other: &U8) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I8 { + data: [u8; 1], +} + +impl I8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for I8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for U8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I8Ref`] for the read-only access, and -/// * [`I8Mut`] for the mutable access -/// -/// to the `I8` data. -/// -/// [`I8Ref`]: struct.I8Ref.html -/// [`I8Mut`]: struct.I8Mut.html -#[derive(Clone, Debug)] -pub struct I8 {} - -/// Read-only access to [`I8`]. -/// -/// [`I8`]: struct.I8.html -#[derive(Clone, Copy)] -pub struct I8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I8 -{ const SCHEMA: &'static str = schema::structs::I8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I8Ref<'a>; +impl I8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since I8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since I8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for I8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I8 {} -impl<'a> I8Ref<'a> { +impl I8 { #[inline] pub fn f(&self) -> i8 { - let value = flatdata_read_bytes!(i8, self.data, 0, 8); + let value = flatdata_read_bytes!(i8, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I8Ref<'a> { +impl std::fmt::Debug for I8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I8") .field("f", &self.f()) @@ -180,114 +206,113 @@ impl<'a> std::fmt::Debug for I8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I8Ref<'a> { +impl std::cmp::PartialEq for I8 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for I8Ref<'a> {} - -/// Mutable access to [`I8`]. -/// -/// [`I8`]: struct.I8.html -pub struct I8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I8Mut<'a> { +impl I8 { #[inline] - pub fn f(&self) -> i8 { - let value = flatdata_read_bytes!(i8, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(i8; value, buffer, 0, 8) + flatdata_write_bytes!(i8; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I8Ref) { + pub fn fill_from(&mut self, other: &I8) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U16 { + data: [u8; 2], +} + +impl U16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } +} + +impl flatdata::Struct for U16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> std::fmt::Debug for I8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U16Ref`] for the read-only access, and -/// * [`U16Mut`] for the mutable access -/// -/// to the `U16` data. -/// -/// [`U16Ref`]: struct.U16Ref.html -/// [`U16Mut`]: struct.U16Mut.html -#[derive(Clone, Debug)] -pub struct U16 {} - -/// Read-only access to [`U16`]. -/// -/// [`U16`]: struct.U16.html -#[derive(Clone, Copy)] -pub struct U16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U16 -{ const SCHEMA: &'static str = schema::structs::U16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U16Ref<'a>; +impl U16 { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since U16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U16Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since U16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for U16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U16 {} -impl<'a> U16Ref<'a> { +impl U16 { #[inline] pub fn f(&self) -> u16 { - let value = flatdata_read_bytes!(u16, self.data, 0, 16); + let value = flatdata_read_bytes!(u16, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U16Ref<'a> { +impl std::fmt::Debug for U16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U16") .field("f", &self.f()) @@ -295,114 +320,113 @@ impl<'a> std::fmt::Debug for U16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U16Ref<'a> { +impl std::cmp::PartialEq for U16 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for U16Ref<'a> {} - -/// Mutable access to [`U16`]. -/// -/// [`U16`]: struct.U16.html -pub struct U16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U16Mut<'a> { +impl U16 { #[inline] - pub fn f(&self) -> u16 { - let value = flatdata_read_bytes!(u16, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u16; value, buffer, 0, 16) + flatdata_write_bytes!(u16; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U16Ref) { + pub fn fill_from(&mut self, other: &U16) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I16 { + data: [u8; 2], +} + +impl I16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } +} + +impl flatdata::Struct for I16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> std::fmt::Debug for U16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I16Ref`] for the read-only access, and -/// * [`I16Mut`] for the mutable access -/// -/// to the `I16` data. -/// -/// [`I16Ref`]: struct.I16Ref.html -/// [`I16Mut`]: struct.I16Mut.html -#[derive(Clone, Debug)] -pub struct I16 {} - -/// Read-only access to [`I16`]. -/// -/// [`I16`]: struct.I16.html -#[derive(Clone, Copy)] -pub struct I16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I16 -{ const SCHEMA: &'static str = schema::structs::I16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} + +impl I16 { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - type Item = I16Ref<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since I16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since I16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I16Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for I16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I16 {} -impl<'a> I16Ref<'a> { +impl I16 { #[inline] pub fn f(&self) -> i16 { - let value = flatdata_read_bytes!(i16, self.data, 0, 16); + let value = flatdata_read_bytes!(i16, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I16Ref<'a> { +impl std::fmt::Debug for I16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I16") .field("f", &self.f()) @@ -410,114 +434,113 @@ impl<'a> std::fmt::Debug for I16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I16Ref<'a> { +impl std::cmp::PartialEq for I16 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for I16Ref<'a> {} - -/// Mutable access to [`I16`]. -/// -/// [`I16`]: struct.I16.html -pub struct I16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I16Mut<'a> { +impl I16 { #[inline] - pub fn f(&self) -> i16 { - let value = flatdata_read_bytes!(i16, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(i16; value, buffer, 0, 16) + flatdata_write_bytes!(i16; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I16Ref) { + pub fn fill_from(&mut self, other: &I16) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U32 { + data: [u8; 4], +} + +impl U32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for U32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> std::fmt::Debug for I16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U32Ref`] for the read-only access, and -/// * [`U32Mut`] for the mutable access -/// -/// to the `U32` data. -/// -/// [`U32Ref`]: struct.U32Ref.html -/// [`U32Mut`]: struct.U32Mut.html -#[derive(Clone, Debug)] -pub struct U32 {} - -/// Read-only access to [`U32`]. -/// -/// [`U32`]: struct.U32.html -#[derive(Clone, Copy)] -pub struct U32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U32 -{ const SCHEMA: &'static str = schema::structs::U32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} + +impl U32 { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - type Item = U32Ref<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since U32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since U32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U32Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for U32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U32 {} -impl<'a> U32Ref<'a> { +impl U32 { #[inline] pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U32Ref<'a> { +impl std::fmt::Debug for U32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U32") .field("f", &self.f()) @@ -525,114 +548,113 @@ impl<'a> std::fmt::Debug for U32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U32Ref<'a> { +impl std::cmp::PartialEq for U32 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for U32Ref<'a> {} - -/// Mutable access to [`U32`]. -/// -/// [`U32`]: struct.U32.html -pub struct U32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U32Mut<'a> { +impl U32 { #[inline] - pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 32) + flatdata_write_bytes!(u32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U32Ref) { + pub fn fill_from(&mut self, other: &U32) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I32 { + data: [u8; 4], +} + +impl I32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for I32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> std::fmt::Debug for U32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I32Ref`] for the read-only access, and -/// * [`I32Mut`] for the mutable access -/// -/// to the `I32` data. -/// -/// [`I32Ref`]: struct.I32Ref.html -/// [`I32Mut`]: struct.I32Mut.html -#[derive(Clone, Debug)] -pub struct I32 {} - -/// Read-only access to [`I32`]. -/// -/// [`I32`]: struct.I32.html -#[derive(Clone, Copy)] -pub struct I32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I32 -{ const SCHEMA: &'static str = schema::structs::I32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I32Ref<'a>; +impl I32 { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since I32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I32Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since I32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for I32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I32 {} -impl<'a> I32Ref<'a> { +impl I32 { #[inline] pub fn f(&self) -> i32 { - let value = flatdata_read_bytes!(i32, self.data, 0, 32); + let value = flatdata_read_bytes!(i32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I32Ref<'a> { +impl std::fmt::Debug for I32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I32") .field("f", &self.f()) @@ -640,114 +662,113 @@ impl<'a> std::fmt::Debug for I32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I32Ref<'a> { +impl std::cmp::PartialEq for I32 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for I32Ref<'a> {} - -/// Mutable access to [`I32`]. -/// -/// [`I32`]: struct.I32.html -pub struct I32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I32Mut<'a> { +impl I32 { #[inline] - pub fn f(&self) -> i32 { - let value = flatdata_read_bytes!(i32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(i32; value, buffer, 0, 32) + flatdata_write_bytes!(i32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I32Ref) { + pub fn fill_from(&mut self, other: &I32) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U64 { + data: [u8; 8], +} + +impl U64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } +} + +impl flatdata::Struct for U64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> std::fmt::Debug for I32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U64Ref`] for the read-only access, and -/// * [`U64Mut`] for the mutable access -/// -/// to the `U64` data. -/// -/// [`U64Ref`]: struct.U64Ref.html -/// [`U64Mut`]: struct.U64Mut.html -#[derive(Clone, Debug)] -pub struct U64 {} - -/// Read-only access to [`U64`]. -/// -/// [`U64`]: struct.U64.html -#[derive(Clone, Copy)] -pub struct U64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U64 -{ const SCHEMA: &'static str = schema::structs::U64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U64Ref<'a>; +impl U64 { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since U64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U64Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since U64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for U64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U64 {} -impl<'a> U64Ref<'a> { +impl U64 { #[inline] pub fn f(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U64Ref<'a> { +impl std::fmt::Debug for U64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U64") .field("f", &self.f()) @@ -755,114 +776,113 @@ impl<'a> std::fmt::Debug for U64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U64Ref<'a> { +impl std::cmp::PartialEq for U64 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for U64Ref<'a> {} - -/// Mutable access to [`U64`]. -/// -/// [`U64`]: struct.U64.html -pub struct U64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U64Mut<'a> { +impl U64 { #[inline] - pub fn f(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U64Ref) { + pub fn fill_from(&mut self, other: &U64) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I64 { + data: [u8; 8], +} + +impl I64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } +} + +impl flatdata::Struct for I64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> std::fmt::Debug for U64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U64Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I64Ref`] for the read-only access, and -/// * [`I64Mut`] for the mutable access -/// -/// to the `I64` data. -/// -/// [`I64Ref`]: struct.I64Ref.html -/// [`I64Mut`]: struct.I64Mut.html -#[derive(Clone, Debug)] -pub struct I64 {} - -/// Read-only access to [`I64`]. -/// -/// [`I64`]: struct.I64.html -#[derive(Clone, Copy)] -pub struct I64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I64 -{ const SCHEMA: &'static str = schema::structs::I64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I64Ref<'a>; +impl I64 { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since I64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since I64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I64Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for I64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I64 {} -impl<'a> I64Ref<'a> { +impl I64 { #[inline] pub fn f(&self) -> i64 { - let value = flatdata_read_bytes!(i64, self.data, 0, 64); + let value = flatdata_read_bytes!(i64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I64Ref<'a> { +impl std::fmt::Debug for I64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I64") .field("f", &self.f()) @@ -870,50 +890,24 @@ impl<'a> std::fmt::Debug for I64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I64Ref<'a> { +impl std::cmp::PartialEq for I64 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for I64Ref<'a> {} - -/// Mutable access to [`I64`]. -/// -/// [`I64`]: struct.I64.html -pub struct I64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I64Mut<'a> { +impl I64 { #[inline] - pub fn f(&self) -> i64 { - let value = flatdata_read_bytes!(i64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(i64; value, buffer, 0, 64) + flatdata_write_bytes!(i64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I64Ref) { + pub fn fill_from(&mut self, other: &I64) { self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for I64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } } - -impl<'a> flatdata::RefMut for I64Mut<'a> {} \ No newline at end of file diff --git a/flatdata-generator/tests/generators/rust_expectations/structs/integers.rs b/flatdata-generator/tests/generators/rust_expectations/structs/integers.rs index ea6a08c7..37985d02 100644 --- a/flatdata-generator/tests/generators/rust_expectations/structs/integers.rs +++ b/flatdata-generator/tests/generators/rust_expectations/structs/integers.rs @@ -1,63 +1,90 @@ -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U8Ref`] for the read-only access, and -/// * [`U8Mut`] for the mutable access -/// -/// to the `U8` data. -/// -/// [`U8Ref`]: struct.U8Ref.html -/// [`U8Mut`]: struct.U8Mut.html -#[derive(Clone, Debug)] -pub struct U8 {} - -/// Read-only access to [`U8`]. -/// -/// [`U8`]: struct.U8.html -#[derive(Clone, Copy)] -pub struct U8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U8 -{ +#[repr(transparent)] +#[derive(Clone)] +pub struct U8 { + data: [u8; 1], +} + +impl U8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for U8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } + const SCHEMA: &'static str = schema::structs::U8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U8Ref<'a>; +impl U8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since U8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since U8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for U8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U8 {} -impl<'a> U8Ref<'a> { +impl U8 { #[inline] pub fn f(&self) -> u8 { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); + let value = flatdata_read_bytes!(u8, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U8Ref<'a> { +impl std::fmt::Debug for U8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U8") .field("f", &self.f()) @@ -65,114 +92,113 @@ impl<'a> std::fmt::Debug for U8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U8Ref<'a> { +impl std::cmp::PartialEq for U8 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for U8Ref<'a> {} - -/// Mutable access to [`U8`]. -/// -/// [`U8`]: struct.U8.html -pub struct U8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U8Mut<'a> { +impl U8 { #[inline] - pub fn f(&self) -> u8 { - let value = flatdata_read_bytes!(u8, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u8; value, buffer, 0, 8) + flatdata_write_bytes!(u8; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U8Ref) { + pub fn fill_from(&mut self, other: &U8) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I8 { + data: [u8; 1], +} + +impl I8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for I8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for U8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I8Ref`] for the read-only access, and -/// * [`I8Mut`] for the mutable access -/// -/// to the `I8` data. -/// -/// [`I8Ref`]: struct.I8Ref.html -/// [`I8Mut`]: struct.I8Mut.html -#[derive(Clone, Debug)] -pub struct I8 {} - -/// Read-only access to [`I8`]. -/// -/// [`I8`]: struct.I8.html -#[derive(Clone, Copy)] -pub struct I8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I8 -{ const SCHEMA: &'static str = schema::structs::I8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I8Ref<'a>; +impl I8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since I8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since I8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for I8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I8 {} -impl<'a> I8Ref<'a> { +impl I8 { #[inline] pub fn f(&self) -> i8 { - let value = flatdata_read_bytes!(i8, self.data, 0, 8); + let value = flatdata_read_bytes!(i8, self.data.as_ptr(), 0, 8); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I8Ref<'a> { +impl std::fmt::Debug for I8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I8") .field("f", &self.f()) @@ -180,114 +206,113 @@ impl<'a> std::fmt::Debug for I8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I8Ref<'a> { +impl std::cmp::PartialEq for I8 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for I8Ref<'a> {} - -/// Mutable access to [`I8`]. -/// -/// [`I8`]: struct.I8.html -pub struct I8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I8Mut<'a> { +impl I8 { #[inline] - pub fn f(&self) -> i8 { - let value = flatdata_read_bytes!(i8, self.data, 0, 8); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(i8; value, buffer, 0, 8) + flatdata_write_bytes!(i8; value, self.data, 0, 8) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I8Ref) { + pub fn fill_from(&mut self, other: &I8) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U16 { + data: [u8; 2], +} + +impl U16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } +} + +impl flatdata::Struct for U16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> std::fmt::Debug for I8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U16Ref`] for the read-only access, and -/// * [`U16Mut`] for the mutable access -/// -/// to the `U16` data. -/// -/// [`U16Ref`]: struct.U16Ref.html -/// [`U16Mut`]: struct.U16Mut.html -#[derive(Clone, Debug)] -pub struct U16 {} - -/// Read-only access to [`U16`]. -/// -/// [`U16`]: struct.U16.html -#[derive(Clone, Copy)] -pub struct U16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U16 -{ const SCHEMA: &'static str = schema::structs::U16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U16Ref<'a>; +impl U16 { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since U16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U16Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since U16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for U16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U16 {} -impl<'a> U16Ref<'a> { +impl U16 { #[inline] pub fn f(&self) -> u16 { - let value = flatdata_read_bytes!(u16, self.data, 0, 16); + let value = flatdata_read_bytes!(u16, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U16Ref<'a> { +impl std::fmt::Debug for U16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U16") .field("f", &self.f()) @@ -295,114 +320,113 @@ impl<'a> std::fmt::Debug for U16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U16Ref<'a> { +impl std::cmp::PartialEq for U16 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for U16Ref<'a> {} - -/// Mutable access to [`U16`]. -/// -/// [`U16`]: struct.U16.html -pub struct U16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U16Mut<'a> { +impl U16 { #[inline] - pub fn f(&self) -> u16 { - let value = flatdata_read_bytes!(u16, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u16; value, buffer, 0, 16) + flatdata_write_bytes!(u16; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U16Ref) { + pub fn fill_from(&mut self, other: &U16) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I16 { + data: [u8; 2], +} + +impl I16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } +} + +impl flatdata::Struct for I16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> std::fmt::Debug for U16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I16Ref`] for the read-only access, and -/// * [`I16Mut`] for the mutable access -/// -/// to the `I16` data. -/// -/// [`I16Ref`]: struct.I16Ref.html -/// [`I16Mut`]: struct.I16Mut.html -#[derive(Clone, Debug)] -pub struct I16 {} - -/// Read-only access to [`I16`]. -/// -/// [`I16`]: struct.I16.html -#[derive(Clone, Copy)] -pub struct I16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I16 -{ const SCHEMA: &'static str = schema::structs::I16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} + +impl I16 { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - type Item = I16Ref<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since I16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since I16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I16Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for I16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I16 {} -impl<'a> I16Ref<'a> { +impl I16 { #[inline] pub fn f(&self) -> i16 { - let value = flatdata_read_bytes!(i16, self.data, 0, 16); + let value = flatdata_read_bytes!(i16, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I16Ref<'a> { +impl std::fmt::Debug for I16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I16") .field("f", &self.f()) @@ -410,114 +434,113 @@ impl<'a> std::fmt::Debug for I16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I16Ref<'a> { +impl std::cmp::PartialEq for I16 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for I16Ref<'a> {} - -/// Mutable access to [`I16`]. -/// -/// [`I16`]: struct.I16.html -pub struct I16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I16Mut<'a> { +impl I16 { #[inline] - pub fn f(&self) -> i16 { - let value = flatdata_read_bytes!(i16, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(i16; value, buffer, 0, 16) + flatdata_write_bytes!(i16; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I16Ref) { + pub fn fill_from(&mut self, other: &I16) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U32 { + data: [u8; 4], +} + +impl U32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for U32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> std::fmt::Debug for I16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U32Ref`] for the read-only access, and -/// * [`U32Mut`] for the mutable access -/// -/// to the `U32` data. -/// -/// [`U32Ref`]: struct.U32Ref.html -/// [`U32Mut`]: struct.U32Mut.html -#[derive(Clone, Debug)] -pub struct U32 {} - -/// Read-only access to [`U32`]. -/// -/// [`U32`]: struct.U32.html -#[derive(Clone, Copy)] -pub struct U32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U32 -{ const SCHEMA: &'static str = schema::structs::U32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} + +impl U32 { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - type Item = U32Ref<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since U32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since U32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U32Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for U32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U32 {} -impl<'a> U32Ref<'a> { +impl U32 { #[inline] pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U32Ref<'a> { +impl std::fmt::Debug for U32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U32") .field("f", &self.f()) @@ -525,114 +548,113 @@ impl<'a> std::fmt::Debug for U32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U32Ref<'a> { +impl std::cmp::PartialEq for U32 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for U32Ref<'a> {} - -/// Mutable access to [`U32`]. -/// -/// [`U32`]: struct.U32.html -pub struct U32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U32Mut<'a> { +impl U32 { #[inline] - pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 32) + flatdata_write_bytes!(u32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U32Ref) { + pub fn fill_from(&mut self, other: &U32) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I32 { + data: [u8; 4], +} + +impl I32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for I32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> std::fmt::Debug for U32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I32Ref`] for the read-only access, and -/// * [`I32Mut`] for the mutable access -/// -/// to the `I32` data. -/// -/// [`I32Ref`]: struct.I32Ref.html -/// [`I32Mut`]: struct.I32Mut.html -#[derive(Clone, Debug)] -pub struct I32 {} - -/// Read-only access to [`I32`]. -/// -/// [`I32`]: struct.I32.html -#[derive(Clone, Copy)] -pub struct I32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I32 -{ const SCHEMA: &'static str = schema::structs::I32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I32Ref<'a>; +impl I32 { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since I32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I32Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since I32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for I32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I32 {} -impl<'a> I32Ref<'a> { +impl I32 { #[inline] pub fn f(&self) -> i32 { - let value = flatdata_read_bytes!(i32, self.data, 0, 32); + let value = flatdata_read_bytes!(i32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I32Ref<'a> { +impl std::fmt::Debug for I32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I32") .field("f", &self.f()) @@ -640,114 +662,113 @@ impl<'a> std::fmt::Debug for I32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I32Ref<'a> { +impl std::cmp::PartialEq for I32 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for I32Ref<'a> {} - -/// Mutable access to [`I32`]. -/// -/// [`I32`]: struct.I32.html -pub struct I32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I32Mut<'a> { +impl I32 { #[inline] - pub fn f(&self) -> i32 { - let value = flatdata_read_bytes!(i32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(i32; value, buffer, 0, 32) + flatdata_write_bytes!(i32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I32Ref) { + pub fn fill_from(&mut self, other: &I32) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U64 { + data: [u8; 8], +} + +impl U64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } +} + +impl flatdata::Struct for U64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> std::fmt::Debug for I32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U64Ref`] for the read-only access, and -/// * [`U64Mut`] for the mutable access -/// -/// to the `U64` data. -/// -/// [`U64Ref`]: struct.U64Ref.html -/// [`U64Mut`]: struct.U64Mut.html -#[derive(Clone, Debug)] -pub struct U64 {} - -/// Read-only access to [`U64`]. -/// -/// [`U64`]: struct.U64.html -#[derive(Clone, Copy)] -pub struct U64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U64 -{ const SCHEMA: &'static str = schema::structs::U64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U64Ref<'a>; +impl U64 { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since U64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U64Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since U64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for U64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U64 {} -impl<'a> U64Ref<'a> { +impl U64 { #[inline] pub fn f(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U64Ref<'a> { +impl std::fmt::Debug for U64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U64") .field("f", &self.f()) @@ -755,114 +776,113 @@ impl<'a> std::fmt::Debug for U64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U64Ref<'a> { +impl std::cmp::PartialEq for U64 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for U64Ref<'a> {} - -/// Mutable access to [`U64`]. -/// -/// [`U64`]: struct.U64.html -pub struct U64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U64Mut<'a> { +impl U64 { #[inline] - pub fn f(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 64) + flatdata_write_bytes!(u64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U64Ref) { + pub fn fill_from(&mut self, other: &U64) { self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I64 { + data: [u8; 8], +} + +impl I64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } +} + +impl flatdata::Struct for I64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> std::fmt::Debug for U64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U64Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I64Ref`] for the read-only access, and -/// * [`I64Mut`] for the mutable access -/// -/// to the `I64` data. -/// -/// [`I64Ref`]: struct.I64Ref.html -/// [`I64Mut`]: struct.I64Mut.html -#[derive(Clone, Debug)] -pub struct I64 {} - -/// Read-only access to [`I64`]. -/// -/// [`I64`]: struct.I64.html -#[derive(Clone, Copy)] -pub struct I64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I64 -{ const SCHEMA: &'static str = schema::structs::I64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I64Ref<'a>; +impl I64 { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since I64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since I64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I64Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for I64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I64 {} -impl<'a> I64Ref<'a> { +impl I64 { #[inline] pub fn f(&self) -> i64 { - let value = flatdata_read_bytes!(i64, self.data, 0, 64); + let value = flatdata_read_bytes!(i64, self.data.as_ptr(), 0, 64); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I64Ref<'a> { +impl std::fmt::Debug for I64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I64") .field("f", &self.f()) @@ -870,50 +890,24 @@ impl<'a> std::fmt::Debug for I64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I64Ref<'a> { +impl std::cmp::PartialEq for I64 { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for I64Ref<'a> {} - -/// Mutable access to [`I64`]. -/// -/// [`I64`]: struct.I64.html -pub struct I64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I64Mut<'a> { +impl I64 { #[inline] - pub fn f(&self) -> i64 { - let value = flatdata_read_bytes!(i64, self.data, 0, 64); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(i64; value, buffer, 0, 64) + flatdata_write_bytes!(i64; value, self.data, 0, 64) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I64Ref) { + pub fn fill_from(&mut self, other: &I64) { self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for I64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } } - -impl<'a> flatdata::RefMut for I64Mut<'a> {} \ No newline at end of file diff --git a/flatdata-generator/tests/generators/rust_expectations/structs/namespaces.rs b/flatdata-generator/tests/generators/rust_expectations/structs/namespaces.rs index 96c06b68..d1418e5b 100644 --- a/flatdata-generator/tests/generators/rust_expectations/structs/namespaces.rs +++ b/flatdata-generator/tests/generators/rust_expectations/structs/namespaces.rs @@ -1,63 +1,90 @@ -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`FooRef`] for the read-only access, and -/// * [`FooMut`] for the mutable access -/// -/// to the `Foo` data. -/// -/// [`FooRef`]: struct.FooRef.html -/// [`FooMut`]: struct.FooMut.html -#[derive(Clone, Debug)] -pub struct Foo {} - -/// Read-only access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -#[derive(Clone, Copy)] -pub struct FooRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for Foo -{ +#[repr(transparent)] +#[derive(Clone)] +pub struct Foo { + data: [u8; 4], +} + +impl Foo { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for Foo { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } + const SCHEMA: &'static str = schema::structs::FOO; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = FooRef<'a>; +impl Foo { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = FooMut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for Foo { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for Foo {} -impl<'a> FooRef<'a> { +impl Foo { #[inline] pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for FooRef<'a> { +impl std::fmt::Debug for Foo { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("Foo") .field("f", &self.f()) @@ -65,55 +92,29 @@ impl<'a> std::fmt::Debug for FooRef<'a> { } } -impl<'a> std::cmp::PartialEq for FooRef<'a> { +impl std::cmp::PartialEq for Foo { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for FooRef<'a> {} - -/// Mutable access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -pub struct FooMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> FooMut<'a> { +impl Foo { #[inline] - pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 32) + flatdata_write_bytes!(u32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &FooRef) { + pub fn fill_from(&mut self, other: &Foo) { self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for FooMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - FooRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for FooMut<'a> {} } +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod m { @@ -130,67 +131,93 @@ struct Foo "#; } +}#[repr(transparent)] +#[derive(Clone)] +pub struct Foo { + data: [u8; 4], } -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`FooRef`] for the read-only access, and -/// * [`FooMut`] for the mutable access -/// -/// to the `Foo` data. -/// -/// [`FooRef`]: struct.FooRef.html -/// [`FooMut`]: struct.FooMut.html -#[derive(Clone, Debug)] -pub struct Foo {} - -/// Read-only access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -#[derive(Clone, Copy)] -pub struct FooRef<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for Foo -{ + +impl Foo { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for Foo { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } + const SCHEMA: &'static str = schema::structs::FOO; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = FooRef<'a>; +impl Foo { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since Foo is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = FooMut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for Foo { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for Foo {} -impl<'a> FooRef<'a> { +impl Foo { #[inline] pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 32); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for FooRef<'a> { +impl std::fmt::Debug for Foo { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("Foo") .field("f", &self.f()) @@ -198,50 +225,24 @@ impl<'a> std::fmt::Debug for FooRef<'a> { } } -impl<'a> std::cmp::PartialEq for FooRef<'a> { +impl std::cmp::PartialEq for Foo { #[inline] fn eq(&self, other: &Self) -> bool { self.f() == other.f() } } -impl<'a> flatdata::Ref for FooRef<'a> {} - -/// Mutable access to [`Foo`]. -/// -/// [`Foo`]: struct.Foo.html -pub struct FooMut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> FooMut<'a> { +impl Foo { #[inline] - pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 32); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 32) + flatdata_write_bytes!(u32; value, self.data, 0, 32) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &FooRef) { + pub fn fill_from(&mut self, other: &Foo) { self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for FooMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - FooRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } } - -impl<'a> flatdata::RefMut for FooMut<'a> {} \ No newline at end of file diff --git a/flatdata-generator/tests/generators/rust_expectations/structs/unaligned.rs b/flatdata-generator/tests/generators/rust_expectations/structs/unaligned.rs index a68bcfd4..1d9bdc4f 100644 --- a/flatdata-generator/tests/generators/rust_expectations/structs/unaligned.rs +++ b/flatdata-generator/tests/generators/rust_expectations/structs/unaligned.rs @@ -1,69 +1,96 @@ -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U8Ref`] for the read-only access, and -/// * [`U8Mut`] for the mutable access -/// -/// to the `U8` data. -/// -/// [`U8Ref`]: struct.U8Ref.html -/// [`U8Mut`]: struct.U8Mut.html -#[derive(Clone, Debug)] -pub struct U8 {} - -/// Read-only access to [`U8`]. -/// -/// [`U8`]: struct.U8.html -#[derive(Clone, Copy)] -pub struct U8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U8 -{ +#[repr(transparent)] +#[derive(Clone)] +pub struct U8 { + data: [u8; 1], +} + +impl U8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for U8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } + const SCHEMA: &'static str = schema::structs::U8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U8Ref<'a>; +impl U8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since U8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U8Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since U8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for U8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U8 {} -impl<'a> U8Ref<'a> { +impl U8 { #[inline] pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 3); unsafe { std::mem::transmute::(value) } } #[inline] pub fn f(&self) -> u8 { - let value = flatdata_read_bytes!(u8, self.data, 3, 5); + let value = flatdata_read_bytes!(u8, self.data.as_ptr(), 3, 5); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U8Ref<'a> { +impl std::fmt::Debug for U8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U8") .field("padding", &self.padding()) @@ -72,136 +99,126 @@ impl<'a> std::fmt::Debug for U8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U8Ref<'a> { +impl std::cmp::PartialEq for U8 { #[inline] fn eq(&self, other: &Self) -> bool { self.padding() == other.padding() && self.f() == other.f() } } -impl<'a> flatdata::Ref for U8Ref<'a> {} - -/// Mutable access to [`U8`]. -/// -/// [`U8`]: struct.U8.html -pub struct U8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U8Mut<'a> { +impl U8 { #[inline] - pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_padding(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 3) + flatdata_write_bytes!(u64; value, self.data, 0, 3) } #[inline] - pub fn f(&self) -> u8 { - let value = flatdata_read_bytes!(u8, self.data, 3, 5); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u8; value, buffer, 3, 5) + flatdata_write_bytes!(u8; value, self.data, 3, 5) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U8Ref) { + pub fn fill_from(&mut self, other: &U8) { self.set_padding(other.padding()); self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I8 { + data: [u8; 1], +} + +impl I8 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 1]} + } +} + +impl flatdata::Struct for I8 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 1]} + } -impl<'a> std::fmt::Debug for U8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I8Ref`] for the read-only access, and -/// * [`I8Mut`] for the mutable access -/// -/// to the `I8` data. -/// -/// [`I8Ref`]: struct.I8Ref.html -/// [`I8Mut`]: struct.I8Mut.html -#[derive(Clone, Debug)] -pub struct I8 {} - -/// Read-only access to [`I8`]. -/// -/// [`I8`]: struct.I8.html -#[derive(Clone, Copy)] -pub struct I8Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I8 -{ const SCHEMA: &'static str = schema::structs::I8; const SIZE_IN_BYTES: usize = 1; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} + +impl I8 { + pub fn new( ) -> Self { + Self{data : [0; 1]} + } - type Item = I8Ref<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 1]) -> &Self { + // Safety: This is safe since I8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 1]) -> &mut Self { + // Safety: This is safe since I8 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) } - type ItemMut = I8Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 1 { + assert_eq!(data.len(), 1); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 1]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + pub fn as_bytes(&self) -> &[u8; 1] { + &self.data + } +} + +impl Default for I8 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I8 {} -impl<'a> I8Ref<'a> { +impl I8 { #[inline] pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 3); unsafe { std::mem::transmute::(value) } } #[inline] pub fn f(&self) -> i8 { - let value = flatdata_read_bytes!(i8, self.data, 3, 5); + let value = flatdata_read_bytes!(i8, self.data.as_ptr(), 3, 5); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I8Ref<'a> { +impl std::fmt::Debug for I8 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I8") .field("padding", &self.padding()) @@ -210,136 +227,126 @@ impl<'a> std::fmt::Debug for I8Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I8Ref<'a> { +impl std::cmp::PartialEq for I8 { #[inline] fn eq(&self, other: &Self) -> bool { self.padding() == other.padding() && self.f() == other.f() } } -impl<'a> flatdata::Ref for I8Ref<'a> {} - -/// Mutable access to [`I8`]. -/// -/// [`I8`]: struct.I8.html -pub struct I8Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I8Mut<'a> { +impl I8 { #[inline] - pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_padding(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 3) + flatdata_write_bytes!(u64; value, self.data, 0, 3) } #[inline] - pub fn f(&self) -> i8 { - let value = flatdata_read_bytes!(i8, self.data, 3, 5); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i8) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 1) - }; - flatdata_write_bytes!(i8; value, buffer, 3, 5) + flatdata_write_bytes!(i8; value, self.data, 3, 5) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I8Ref) { + pub fn fill_from(&mut self, other: &I8) { self.set_padding(other.padding()); self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U16 { + data: [u8; 2], +} + +impl U16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } +} + +impl flatdata::Struct for U16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> std::fmt::Debug for I8Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I8Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I8Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U16Ref`] for the read-only access, and -/// * [`U16Mut`] for the mutable access -/// -/// to the `U16` data. -/// -/// [`U16Ref`]: struct.U16Ref.html -/// [`U16Mut`]: struct.U16Mut.html -#[derive(Clone, Debug)] -pub struct U16 {} - -/// Read-only access to [`U16`]. -/// -/// [`U16`]: struct.U16.html -#[derive(Clone, Copy)] -pub struct U16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U16 -{ const SCHEMA: &'static str = schema::structs::U16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U16Ref<'a>; +impl U16 { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since U16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U16Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since U16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for U16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U16 {} -impl<'a> U16Ref<'a> { +impl U16 { #[inline] pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 3); unsafe { std::mem::transmute::(value) } } #[inline] pub fn f(&self) -> u16 { - let value = flatdata_read_bytes!(u16, self.data, 3, 13); + let value = flatdata_read_bytes!(u16, self.data.as_ptr(), 3, 13); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U16Ref<'a> { +impl std::fmt::Debug for U16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U16") .field("padding", &self.padding()) @@ -348,136 +355,126 @@ impl<'a> std::fmt::Debug for U16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U16Ref<'a> { +impl std::cmp::PartialEq for U16 { #[inline] fn eq(&self, other: &Self) -> bool { self.padding() == other.padding() && self.f() == other.f() } } -impl<'a> flatdata::Ref for U16Ref<'a> {} - -/// Mutable access to [`U16`]. -/// -/// [`U16`]: struct.U16.html -pub struct U16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U16Mut<'a> { +impl U16 { #[inline] - pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_padding(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 3) + flatdata_write_bytes!(u64; value, self.data, 0, 3) } #[inline] - pub fn f(&self) -> u16 { - let value = flatdata_read_bytes!(u16, self.data, 3, 13); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u16; value, buffer, 3, 13) + flatdata_write_bytes!(u16; value, self.data, 3, 13) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U16Ref) { + pub fn fill_from(&mut self, other: &U16) { self.set_padding(other.padding()); self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I16 { + data: [u8; 2], +} + +impl I16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } +} + +impl flatdata::Struct for I16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> std::fmt::Debug for U16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I16Ref`] for the read-only access, and -/// * [`I16Mut`] for the mutable access -/// -/// to the `I16` data. -/// -/// [`I16Ref`]: struct.I16Ref.html -/// [`I16Mut`]: struct.I16Mut.html -#[derive(Clone, Debug)] -pub struct I16 {} - -/// Read-only access to [`I16`]. -/// -/// [`I16`]: struct.I16.html -#[derive(Clone, Copy)] -pub struct I16Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I16 -{ const SCHEMA: &'static str = schema::structs::I16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I16Ref<'a>; +impl I16 { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since I16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I16Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since I16 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for I16 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I16 {} -impl<'a> I16Ref<'a> { +impl I16 { #[inline] pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 3); unsafe { std::mem::transmute::(value) } } #[inline] pub fn f(&self) -> i16 { - let value = flatdata_read_bytes!(i16, self.data, 3, 13); + let value = flatdata_read_bytes!(i16, self.data.as_ptr(), 3, 13); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I16Ref<'a> { +impl std::fmt::Debug for I16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I16") .field("padding", &self.padding()) @@ -486,136 +483,126 @@ impl<'a> std::fmt::Debug for I16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I16Ref<'a> { +impl std::cmp::PartialEq for I16 { #[inline] fn eq(&self, other: &Self) -> bool { self.padding() == other.padding() && self.f() == other.f() } } -impl<'a> flatdata::Ref for I16Ref<'a> {} - -/// Mutable access to [`I16`]. -/// -/// [`I16`]: struct.I16.html -pub struct I16Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I16Mut<'a> { +impl I16 { #[inline] - pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_padding(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 3) + flatdata_write_bytes!(u64; value, self.data, 0, 3) } #[inline] - pub fn f(&self) -> i16 { - let value = flatdata_read_bytes!(i16, self.data, 3, 13); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i16) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(i16; value, buffer, 3, 13) + flatdata_write_bytes!(i16; value, self.data, 3, 13) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I16Ref) { + pub fn fill_from(&mut self, other: &I16) { self.set_padding(other.padding()); self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U32 { + data: [u8; 4], +} + +impl U32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for U32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> std::fmt::Debug for I16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I16Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U32Ref`] for the read-only access, and -/// * [`U32Mut`] for the mutable access -/// -/// to the `U32` data. -/// -/// [`U32Ref`]: struct.U32Ref.html -/// [`U32Mut`]: struct.U32Mut.html -#[derive(Clone, Debug)] -pub struct U32 {} - -/// Read-only access to [`U32`]. -/// -/// [`U32`]: struct.U32.html -#[derive(Clone, Copy)] -pub struct U32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U32 -{ const SCHEMA: &'static str = schema::structs::U32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U32Ref<'a>; +impl U32 { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since U32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U32Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since U32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for U32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U32 {} -impl<'a> U32Ref<'a> { +impl U32 { #[inline] pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 3); unsafe { std::mem::transmute::(value) } } #[inline] pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 3, 29); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 3, 29); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U32Ref<'a> { +impl std::fmt::Debug for U32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U32") .field("padding", &self.padding()) @@ -624,136 +611,126 @@ impl<'a> std::fmt::Debug for U32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U32Ref<'a> { +impl std::cmp::PartialEq for U32 { #[inline] fn eq(&self, other: &Self) -> bool { self.padding() == other.padding() && self.f() == other.f() } } -impl<'a> flatdata::Ref for U32Ref<'a> {} - -/// Mutable access to [`U32`]. -/// -/// [`U32`]: struct.U32.html -pub struct U32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U32Mut<'a> { +impl U32 { #[inline] - pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_padding(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 3) + flatdata_write_bytes!(u64; value, self.data, 0, 3) } #[inline] - pub fn f(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 3, 29); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 3, 29) + flatdata_write_bytes!(u32; value, self.data, 3, 29) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U32Ref) { + pub fn fill_from(&mut self, other: &U32) { self.set_padding(other.padding()); self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I32 { + data: [u8; 4], +} + +impl I32 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} + } +} + +impl flatdata::Struct for I32 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> std::fmt::Debug for U32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I32Ref`] for the read-only access, and -/// * [`I32Mut`] for the mutable access -/// -/// to the `I32` data. -/// -/// [`I32Ref`]: struct.I32Ref.html -/// [`I32Mut`]: struct.I32Mut.html -#[derive(Clone, Debug)] -pub struct I32 {} - -/// Read-only access to [`I32`]. -/// -/// [`I32`]: struct.I32.html -#[derive(Clone, Copy)] -pub struct I32Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I32 -{ const SCHEMA: &'static str = schema::structs::I32; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I32Ref<'a>; +impl I32 { + pub fn new( ) -> Self { + Self{data : [0; 4]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 4]) -> &Self { + // Safety: This is safe since I32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } + + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 4]) -> &mut Self { + // Safety: This is safe since I32 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I32Mut<'a>; + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 4 { + assert_eq!(data.len(), 4); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 4]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 4] { + &self.data + } +} + +impl Default for I32 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I32 {} -impl<'a> I32Ref<'a> { +impl I32 { #[inline] pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 3); unsafe { std::mem::transmute::(value) } } #[inline] pub fn f(&self) -> i32 { - let value = flatdata_read_bytes!(i32, self.data, 3, 29); + let value = flatdata_read_bytes!(i32, self.data.as_ptr(), 3, 29); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I32Ref<'a> { +impl std::fmt::Debug for I32 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I32") .field("padding", &self.padding()) @@ -762,136 +739,126 @@ impl<'a> std::fmt::Debug for I32Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I32Ref<'a> { +impl std::cmp::PartialEq for I32 { #[inline] fn eq(&self, other: &Self) -> bool { self.padding() == other.padding() && self.f() == other.f() } } -impl<'a> flatdata::Ref for I32Ref<'a> {} - -/// Mutable access to [`I32`]. -/// -/// [`I32`]: struct.I32.html -pub struct I32Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I32Mut<'a> { +impl I32 { #[inline] - pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_padding(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 3) + flatdata_write_bytes!(u64; value, self.data, 0, 3) } #[inline] - pub fn f(&self) -> i32 { - let value = flatdata_read_bytes!(i32, self.data, 3, 29); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(i32; value, buffer, 3, 29) + flatdata_write_bytes!(i32; value, self.data, 3, 29) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I32Ref) { + pub fn fill_from(&mut self, other: &I32) { self.set_padding(other.padding()); self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct U64 { + data: [u8; 8], +} + +impl U64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } +} + +impl flatdata::Struct for U64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> std::fmt::Debug for I32Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I32Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for I32Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`U64Ref`] for the read-only access, and -/// * [`U64Mut`] for the mutable access -/// -/// to the `U64` data. -/// -/// [`U64Ref`]: struct.U64Ref.html -/// [`U64Mut`]: struct.U64Mut.html -#[derive(Clone, Debug)] -pub struct U64 {} - -/// Read-only access to [`U64`]. -/// -/// [`U64`]: struct.U64.html -#[derive(Clone, Copy)] -pub struct U64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for U64 -{ const SCHEMA: &'static str = schema::structs::U64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = U64Ref<'a>; +impl U64 { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since U64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = U64Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since U64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for U64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for U64 {} -impl<'a> U64Ref<'a> { +impl U64 { #[inline] pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 3); unsafe { std::mem::transmute::(value) } } #[inline] pub fn f(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 3, 61); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 3, 61); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for U64Ref<'a> { +impl std::fmt::Debug for U64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("U64") .field("padding", &self.padding()) @@ -900,136 +867,126 @@ impl<'a> std::fmt::Debug for U64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for U64Ref<'a> { +impl std::cmp::PartialEq for U64 { #[inline] fn eq(&self, other: &Self) -> bool { self.padding() == other.padding() && self.f() == other.f() } } -impl<'a> flatdata::Ref for U64Ref<'a> {} - -/// Mutable access to [`U64`]. -/// -/// [`U64`]: struct.U64.html -pub struct U64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> U64Mut<'a> { +impl U64 { #[inline] - pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_padding(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 3) + flatdata_write_bytes!(u64; value, self.data, 0, 3) } #[inline] - pub fn f(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 3, 61); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 3, 61) + flatdata_write_bytes!(u64; value, self.data, 3, 61) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &U64Ref) { + pub fn fill_from(&mut self, other: &U64) { self.set_padding(other.padding()); self.set_f(other.f()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct I64 { + data: [u8; 8], +} + +impl I64 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 8]} + } +} + +impl flatdata::Struct for I64 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 8]} + } -impl<'a> std::fmt::Debug for U64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - U64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> flatdata::RefMut for U64Mut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`I64Ref`] for the read-only access, and -/// * [`I64Mut`] for the mutable access -/// -/// to the `I64` data. -/// -/// [`I64Ref`]: struct.I64Ref.html -/// [`I64Mut`]: struct.I64Mut.html -#[derive(Clone, Debug)] -pub struct I64 {} - -/// Read-only access to [`I64`]. -/// -/// [`I64`]: struct.I64.html -#[derive(Clone, Copy)] -pub struct I64Ref<'a> { - pub(crate) data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> flatdata::Struct<'a> for I64 -{ const SCHEMA: &'static str = schema::structs::I64; const SIZE_IN_BYTES: usize = 8; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = I64Ref<'a>; +impl I64 { + pub fn new( ) -> Self { + Self{data : [0; 8]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 8]) -> &Self { + // Safety: This is safe since I64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = I64Mut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 8]) -> &mut Self { + // Safety: This is safe since I64 is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, flatdata::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 8 { + assert_eq!(data.len(), 8); + return Err(flatdata::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 8]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 8] { + &self.data + } +} + +impl Default for I64 { + fn default( ) -> Self { + Self::new( ) } } impl flatdata::NoOverlap for I64 {} -impl<'a> I64Ref<'a> { +impl I64 { #[inline] pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 3); unsafe { std::mem::transmute::(value) } } #[inline] pub fn f(&self) -> i64 { - let value = flatdata_read_bytes!(i64, self.data, 3, 61); + let value = flatdata_read_bytes!(i64, self.data.as_ptr(), 3, 61); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for I64Ref<'a> { +impl std::fmt::Debug for I64 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("I64") .field("padding", &self.padding()) @@ -1038,66 +995,31 @@ impl<'a> std::fmt::Debug for I64Ref<'a> { } } -impl<'a> std::cmp::PartialEq for I64Ref<'a> { +impl std::cmp::PartialEq for I64 { #[inline] fn eq(&self, other: &Self) -> bool { self.padding() == other.padding() && self.f() == other.f() } } -impl<'a> flatdata::Ref for I64Ref<'a> {} - -/// Mutable access to [`I64`]. -/// -/// [`I64`]: struct.I64.html -pub struct I64Mut<'a> { - pub(crate) data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> I64Mut<'a> { +impl I64 { #[inline] - pub fn padding(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 3); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_padding(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 3) + flatdata_write_bytes!(u64; value, self.data, 0, 3) } #[inline] - pub fn f(&self) -> i64 { - let value = flatdata_read_bytes!(i64, self.data, 3, 61); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_f(&mut self, value: i64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 8) - }; - flatdata_write_bytes!(i64; value, buffer, 3, 61) + flatdata_write_bytes!(i64; value, self.data, 3, 61) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &I64Ref) { + pub fn fill_from(&mut self, other: &I64) { self.set_padding(other.padding()); self.set_f(other.f()); } } - -impl<'a> std::fmt::Debug for I64Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - I64Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } } - -impl<'a> flatdata::RefMut for I64Mut<'a> {} \ No newline at end of file diff --git a/flatdata-rs/lib/src/arrayview.rs b/flatdata-rs/lib/src/arrayview.rs index d68f8576..a8854ea8 100644 --- a/flatdata-rs/lib/src/arrayview.rs +++ b/flatdata-rs/lib/src/arrayview.rs @@ -1,242 +1,47 @@ -use crate::{ - structs::{RefFactory, Struct}, - vector::Vector, -}; +use crate::error::ResourceStorageError; +use crate::structs::Struct; -use std::{ - fmt, iter, marker, - ops::{Bound, RangeBounds}, -}; - -/// A read-only view on a contiguous sequence of flatdata structs of the same -/// type `T`. -/// -/// The sequence is written using [`Vector`] or [`ExternalVector`]. For detailed -/// examples see either of the two. -/// -/// An archive provides a getter for each vector resource, which returns an -/// array view. -/// -/// [`Vector`]: struct.Vector.html -/// [`ExternalVector`]: struct.ExternalVector.html -#[derive(Clone)] -pub struct ArrayView<'a, T> -where - T: RefFactory, -{ - data: &'a [u8], - _phantom: marker::PhantomData, -} - -impl<'a, T> ArrayView<'a, T> +/// Enhanced slices of flatdata Structs so that they can be created from bytes / converted to bytes +pub trait SliceExt<'a> where - T: RefFactory, + Self: Sized, { - /// Creates a new `ArrayView` to the data at the given address. - /// - /// The returned array view does not own the data. - pub fn new(data: &'a [u8]) -> Self { - Self { - data, - _phantom: marker::PhantomData, - } - } - - /// Number of elements in the array. - pub fn len(&self) -> usize { - if ::IS_OVERLAPPING_WITH_NEXT { - self.data.len() / ::SIZE_IN_BYTES - 1 - } else { - self.data.len() / ::SIZE_IN_BYTES - } - } - - /// Returns `true` if the array is empty. - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Returns a read-only handle to the element in the array at position - /// `index`. - /// - /// # Panics - /// - /// Panics if index is greater than or equal to `ArrayView::len()`. - pub fn at(&self, index: usize) -> >::Item { - assert!(index < self.len()); - let index = self.data_index(index); - T::create(&self.data[index..]) - } - - /// Slices this array view by a given range. - /// - /// # Panics - /// - /// Panics if the range is outside of bounds of array view. - pub fn slice>(&self, range: R) -> Self { - let data_start = match range.start_bound() { - Bound::Included(&idx) => self.data_index(idx), - Bound::Excluded(&idx) => self.data_index(idx + 1), - Bound::Unbounded => 0, - }; - let sentinel = ::IS_OVERLAPPING_WITH_NEXT as usize; - let data_end = match range.end_bound() { - Bound::Included(&idx) => self.data_index(idx + 1 + sentinel), - Bound::Excluded(&idx) => self.data_index(idx + sentinel), - Bound::Unbounded => self.data.len(), - }; - Self::new(&self.data[data_start..data_end]) - } - - /// Returns an iterator to the elements of the array. - pub fn iter(&self) -> ArrayViewIter<'a, T> { - ArrayViewIter { view: self.clone() } - } - - /// Returns a raw bytes representation of the underlying array data. - pub fn as_bytes(&self) -> &[u8] { - self.data - } + /// Create a slice from an array of bytes + fn from_bytes(data: &'a [u8]) -> Result; - fn data_index(&self, index: usize) -> usize { - index * ::SIZE_IN_BYTES - } -} - -impl<'a, T> From<&'a Vector> for ArrayView<'a, T> -where - T: RefFactory, -{ - fn from(v: &'a Vector) -> Self { - v.as_view() - } + /// Get byte representation of the slice + fn as_bytes(&self) -> &'a [u8]; } -pub(crate) fn debug_format<'a, T>( - name: &str, - iter: ArrayViewIter<'a, T>, - f: &mut fmt::Formatter, -) -> fmt::Result +impl<'a, T> SliceExt<'a> for &'a [T] where - T: RefFactory, + T: Struct, { - let len = iter.len(); - let preview: Vec<_> = iter.take(super::DEBUG_PREVIEW_LEN).collect(); - write!( - f, - "{} {{ len: {}, data: {:?}{} }}", - name, - len, - preview, - if len <= super::DEBUG_PREVIEW_LEN { - "" - } else { - "..." + fn from_bytes(mut data: &[u8]) -> Result { + if data.len() % T::SIZE_IN_BYTES != 0 { + return Err(ResourceStorageError::UnexpectedDataSize); } - ) -} - -impl<'a, T> fmt::Debug for ArrayView<'a, T> -where - T: RefFactory, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - debug_format("ArrayView", self.iter(), f) - } -} - -impl<'a, T> IntoIterator for ArrayView<'a, T> -where - T: RefFactory, -{ - type Item = as Iterator>::Item; - type IntoIter = ArrayViewIter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, T> IntoIterator for &ArrayView<'a, T> -where - T: RefFactory, -{ - type Item = as Iterator>::Item; - type IntoIter = ArrayViewIter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, T> AsRef<[u8]> for ArrayView<'a, T> -where - T: RefFactory, -{ - fn as_ref(&self) -> &[u8] { - self.as_bytes() - } -} - -/// Iterator through elements of `ArrayView`. -#[derive(Clone)] -pub struct ArrayViewIter<'a, T> -where - T: RefFactory, -{ - view: ArrayView<'a, T>, -} - -impl<'a, T> iter::Iterator for ArrayViewIter<'a, T> -where - T: RefFactory, -{ - type Item = >::Item; - fn next(&mut self) -> Option { - if !self.view.is_empty() { - let element = self.view.at(0); - self.view = self.view.slice(1..); - Some(element) - } else { - None + if T::IS_OVERLAPPING_WITH_NEXT { + if data.len() < T::SIZE_IN_BYTES { + return Err(ResourceStorageError::UnexpectedDataSize); + } + data = &data[..data.len() - T::SIZE_IN_BYTES]; } - } -} - -impl<'a, T> iter::ExactSizeIterator for ArrayViewIter<'a, T> -where - T: RefFactory, -{ - fn len(&self) -> usize { - self.view.len() - } -} - -impl<'a, T> iter::DoubleEndedIterator for ArrayViewIter<'a, T> -where - T: RefFactory, -{ - fn next_back(&mut self) -> Option { - if !self.view.is_empty() { - let last_pos = self.view.len() - 1; - let element = self.view.at(last_pos); - self.view = self.view.slice(..last_pos); - Some(element) - } else { - None + unsafe { + Ok(std::slice::from_raw_parts( + data.as_ptr() as *const T, + data.len() / T::SIZE_IN_BYTES, + )) } } -} -// we always check -> iterator is already fused -impl<'a, T> iter::FusedIterator for ArrayViewIter<'a, T> where T: RefFactory {} - -impl<'a, T> fmt::Debug for ArrayViewIter<'a, T> -where - T: RefFactory, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - debug_format("ArrayViewIter", self.clone(), f) + fn as_bytes(&self) -> &'a [u8] { + let len = if T::IS_OVERLAPPING_WITH_NEXT { + self.len() + 1 + } else { + self.len() + }; + unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, len * T::SIZE_IN_BYTES) } } } @@ -245,41 +50,48 @@ where mod test { use super::*; use crate::{ - memory, structs::Struct, test::{A, B, R}, + Vector, }; #[test] fn range() { let mut vec: Vector = Vector::with_len(3); - vec.at_mut(0).set_first_x(10); - vec.at_mut(1).set_first_x(20); - vec.at_mut(2).set_first_x(30); + vec[0].set_first_x(10); + vec[1].set_first_x(20); + vec[2].set_first_x(30); + + assert_eq!(vec.len(), 3); + assert_eq!(vec[0].x(), 10..20); + assert_eq!(vec[1].x(), 20..30); + assert_eq!(vec[2].x(), 30..0); + + assert_eq!(vec[0..1].len(), 1); + assert_eq!(vec[0..1][0].x(), 10..20); let view = vec.as_view(); assert_eq!(view.len(), 2); - assert_eq!(view.at(0).x(), 10..20); - assert_eq!(view.at(1).x(), 20..30); + assert_eq!(view[0].x(), 10..20); + assert_eq!(view[1].x(), 20..30); - assert_eq!(view.slice(0..1).len(), 1); - assert_eq!(view.slice(0..1).at(0).x(), 10..20); + assert_eq!(vec[0..1].len(), 1); + assert_eq!(vec[0..1][0].x(), 10..20); } #[test] fn into_iter() { for _ in create_values(10).as_view() {} - for _ in &create_values(10).as_view() {} } #[test] fn new_and_clone() { let mut buffer = vec![255_u8; A::SIZE_IN_BYTES]; - buffer.extend(vec![0_u8; A::SIZE_IN_BYTES * 10 + memory::PADDING_SIZE]); - let data = &buffer[..buffer.len() - memory::PADDING_SIZE]; - let view: ArrayView = ArrayView::new(&data); + buffer.extend(vec![0_u8; A::SIZE_IN_BYTES * 10]); + let data = &buffer[..]; + let view = <&[A]>::from_bytes(&data).unwrap(); assert_eq!(11, view.len()); - let first = view.at(0); + let first = &view[0]; assert_eq!(65535, first.x()); assert_eq!(65535, first.y()); for x in view.iter().skip(1) { @@ -290,7 +102,7 @@ mod test { let x = { // test clone and lifetime of returned reference let view_copy = view.clone(); - view_copy.at(0) + &view_copy[0] }; assert_eq!(65535, x.x()); assert_eq!(65535, x.y()); @@ -307,19 +119,12 @@ mod test { fn create_values(size: usize) -> Vector { let mut v: Vector = Vector::with_len(size); for i in 0..size as u32 { - let mut a = v.at_mut(i as usize); + let a = &mut v[i as usize]; a.set_id(i); } v } - #[test] - fn from() { - let v = create_values(10); - let x: ArrayView<_> = (&v).into(); - assert_eq!(x.len(), 10); - } - #[test] fn reverse() { let v = create_values(10); @@ -350,23 +155,23 @@ mod test { #[test] fn slice() { let v = create_values(10); - let view: ArrayView<_> = (&v).into(); + let view = v.as_view(); assert_eq!(view.len(), 10); - assert_eq!(view.slice(2..).len(), 8); - assert_eq!(view.slice(2..).iter().next().unwrap().id(), 2); - assert_eq!(view.slice(..8).len(), 8); - assert_eq!(view.slice(..8).iter().next().unwrap().id(), 0); - assert_eq!(view.slice(2..8).len(), 6); - assert_eq!(view.slice(2..8).iter().next().unwrap().id(), 2); + assert_eq!(view[2..].len(), 8); + assert_eq!(view[2..].iter().next().unwrap().id(), 2); + assert_eq!(view[..8].len(), 8); + assert_eq!(view[..8].iter().next().unwrap().id(), 0); + assert_eq!(view[2..8].len(), 6); + assert_eq!(view[2..8].iter().next().unwrap().id(), 2); } #[test] fn debug() { - let v = create_values(100); + let v = create_values(10); let view = v.as_view(); - let content = " { len: 100, data: [\ + let content = "[\ B { id: 0 }, \ B { id: 1 }, \ B { id: 2 }, \ @@ -377,20 +182,17 @@ mod test { B { id: 7 }, \ B { id: 8 }, \ B { id: 9 }\ - ]... }"; + ]"; - assert_eq!(format!("{:?}", view), "ArrayView".to_string() + content); + assert_eq!(format!("{:?}", view), content); assert_eq!( format!("{:?}", view.iter()), - "ArrayViewIter".to_string() + content + "Iter(".to_string() + content + ")" ); let mut iter = view.iter(); - for _ in 0..99 { + for _ in 0..9 { iter.next(); } - assert_eq!( - format!("{:?}", iter), - "ArrayViewIter { len: 1, data: [B { id: 99 }] }" - ); + assert_eq!(format!("{:?}", iter), "Iter([B { id: 9 }])"); } } diff --git a/flatdata-rs/lib/src/error.rs b/flatdata-rs/lib/src/error.rs index d3059ebc..f3e3b01f 100644 --- a/flatdata-rs/lib/src/error.rs +++ b/flatdata-rs/lib/src/error.rs @@ -18,6 +18,8 @@ pub enum ResourceStorageError { /// Indicates that schema for the resource with stored name is missing in /// resource storage. MissingSchema(String), + /// Indicates that part of the data is missing, e.g. one file of a multi_vector + MissingData, /// Indicates that the schema stored in resource storage differs from the /// expected schema. WrongSignature { @@ -55,6 +57,7 @@ impl error::Error for ResourceStorageError { match *self { ResourceStorageError::Io(_, _) => "resource io error", ResourceStorageError::MissingSchema(_) => "schema of resource is missing", + ResourceStorageError::MissingData => "resource has partially missing data", ResourceStorageError::UnexpectedDataSize => "resource has unexpected size", ResourceStorageError::Utf8Error(_) => "utf8 error in schema", ResourceStorageError::WrongSignature { .. } => "schema is not matching expected schema", diff --git a/flatdata-rs/lib/src/lib.rs b/flatdata-rs/lib/src/lib.rs index 861246fc..11a54b5f 100644 --- a/flatdata-rs/lib/src/lib.rs +++ b/flatdata-rs/lib/src/lib.rs @@ -159,7 +159,6 @@ mod multiarrayview; mod multivector; mod rawdata; mod storage; -mod structbuf; mod structs; mod vector; @@ -171,7 +170,7 @@ pub mod test; pub use crate::{ archive::*, - arrayview::ArrayView, + arrayview::SliceExt, error::*, filestorage::FileResourceStorage, generator::*, @@ -180,11 +179,7 @@ pub use crate::{ multiarrayview::MultiArrayView, multivector::MultiVector, rawdata::RawData, - storage::{ - create_archive, create_external_vector, create_multi_vector, MemoryDescriptor, - ResourceStorage, - }, - structbuf::StructBuf, + storage::{create_archive, create_external_vector, create_multi_vector, ResourceStorage}, structs::*, vector::*, }; diff --git a/flatdata-rs/lib/src/multiarrayview.rs b/flatdata-rs/lib/src/multiarrayview.rs index 9c3da5fe..1080e3cf 100644 --- a/flatdata-rs/lib/src/multiarrayview.rs +++ b/flatdata-rs/lib/src/multiarrayview.rs @@ -1,9 +1,6 @@ -use crate::{ - arrayview::ArrayView, - structs::{IndexStruct, VariadicRef, VariadicRefFactory, VariadicStruct}, -}; +use crate::structs::{IndexStruct, VariadicRef, VariadicRefFactory, VariadicStruct}; -use std::{fmt, iter, marker, ops::RangeBounds}; +use std::{fmt, iter, marker}; /// A read-only view on a multivector. /// @@ -11,16 +8,24 @@ use std::{fmt, iter, marker, ops::RangeBounds}; /// [`MultiVector`]. /// /// [`MultiVector`]: struct.MultiVector.html -#[derive(Clone)] pub struct MultiArrayView<'a, Ts> where Ts: VariadicRefFactory, { - index: ArrayView<'a, >::Index>, + index: &'a [Ts::Index], data: &'a [u8], _phantom: marker::PhantomData, } +impl<'a, Ts> Clone for MultiArrayView<'a, Ts> +where + Ts: VariadicRefFactory, +{ + fn clone(&self) -> Self { + Self { ..*self } + } +} + impl<'a, Ts> MultiArrayView<'a, Ts> where Ts: VariadicRefFactory, @@ -28,13 +33,10 @@ where /// Creates a new `MultiArrayView` to the data at the given address. /// /// The returned array view does not own the data. - pub fn new( - index: ArrayView<'a, >::Index>, - data_mem_descr: &'a [u8], - ) -> Self { + pub fn new(index: &'a [Ts::Index], data: &'a [u8]) -> Self { Self { index, - data: &data_mem_descr, + data: &data, _phantom: marker::PhantomData, } } @@ -59,7 +61,7 @@ where /// /// Panics if index is greater than or equal to `MultiArrayView::len()`. pub fn at(&self, index: usize) -> MultiArrayViewItemIter<'a, Ts> { - let range = <>::Index as IndexStruct>::range(self.index.at(index)); + let range = ::range(&self.index[index]); MultiArrayViewItemIter { data: &self.data[range], _phantom: marker::PhantomData, @@ -71,8 +73,11 @@ where /// # Panics /// /// Panics if the range is outside of bounds of array view. - pub fn slice>(&self, range: R) -> Self { - Self::new(self.index.slice(range), self.data) + pub fn slice>( + &self, + range: R, + ) -> Self { + Self::new(&self.index[range], self.data) } /// Returns an iterator through the indexed items of the array. @@ -264,10 +269,10 @@ mod tests { for i in 0..size { let mut item = mv.grow().expect("grow failed"); - let mut b = item.add_b(); + let b = item.add_b(); b.set_id(i as u32); - let mut a = item.add_a(); + let a = item.add_a(); a.set_x((i + size) as u32); a.set_y((i + 2 * size) as u32); } diff --git a/flatdata-rs/lib/src/multivector.rs b/flatdata-rs/lib/src/multivector.rs index 1bc413d5..dcd51941 100644 --- a/flatdata-rs/lib/src/multivector.rs +++ b/flatdata-rs/lib/src/multivector.rs @@ -1,6 +1,5 @@ use crate::{ error::ResourceStorageError, - memory, multiarrayview::MultiArrayView, storage::ResourceHandle, structs::{IndexStruct, VariadicRefFactory, VariadicStruct}, @@ -99,7 +98,7 @@ pub struct MultiVector<'a, Ts> where Ts: VariadicRefFactory, { - index: ExternalVector<'a, >::Index>, + index: ExternalVector<'a, Ts::Index>, data: Vec, data_handle: ResourceHandle<'a>, size_flushed: usize, @@ -111,13 +110,10 @@ where Ts: VariadicRefFactory, { /// Creates an empty multivector. - pub fn new( - index: ExternalVector<'a, >::Index>, - data_handle: ResourceHandle<'a>, - ) -> Self { + pub fn new(index: ExternalVector<'a, Ts::Index>, data_handle: ResourceHandle<'a>) -> Self { Self { index, - data: vec![0; memory::PADDING_SIZE], + data: Vec::new(), data_handle, size_flushed: 0, _phantom: marker::PhantomData, @@ -146,21 +142,15 @@ where /// /// Only data is flushed. fn flush(&mut self) -> io::Result<()> { - self.data_handle - .borrow_mut() - .write(&self.data[..self.data.len() - memory::PADDING_SIZE])?; - self.size_flushed += self.data.len() - memory::PADDING_SIZE; + self.data_handle.borrow_mut().write(&self.data)?; + self.size_flushed += self.data.len(); self.data.clear(); - self.data.resize(memory::PADDING_SIZE, 0); Ok(()) } fn add_to_index(&mut self) -> io::Result<()> { let idx_mut = self.index.grow()?; - <>::Index as IndexStruct>::set_index( - idx_mut, - self.size_flushed + self.data.len() - memory::PADDING_SIZE, - ); + Ts::Index::set_index(idx_mut, self.size_flushed + self.data.len()); Ok(()) } @@ -192,7 +182,6 @@ where #[allow(dead_code)] mod tests { use crate::{ - arrayview::ArrayView, memstorage::MemoryResourceStorage, multiarrayview::MultiArrayView, storage::{create_multi_vector, ResourceStorage}, @@ -208,14 +197,14 @@ mod tests { { let mut item = mv.grow().expect("grow failed"); { - let mut a = item.add_a(); + let a = item.add_a(); a.set_x(1); a.set_y(2); assert_eq!(a.x(), 1); assert_eq!(a.y(), 2); } { - let mut b = item.add_a(); + let b = item.add_a(); b.set_x(3); b.set_y(4); assert_eq!(b.x(), 3); @@ -240,7 +229,8 @@ mod tests { let index_resource = storage .read_and_check_schema("multivector_index", "index(Some schema)") .expect("read_and_check_schema failed"); - let index: ArrayView = ArrayView::new(&index_resource); + use crate::SliceExt; + let index = <&[IndexType16]>::from_bytes(&index_resource).expect("Corrupted data"); let resource = storage .read_and_check_schema("multivector", "Some schema") .expect("read_and_check_schema failed"); diff --git a/flatdata-rs/lib/src/storage.rs b/flatdata-rs/lib/src/storage.rs index ce0750ce..021e73d6 100644 --- a/flatdata-rs/lib/src/storage.rs +++ b/flatdata-rs/lib/src/storage.rs @@ -13,9 +13,8 @@ use std::{ io::{self, Seek, Write}, mem, ops::DerefMut, - ptr, rc::Rc, - slice, str, + str, }; use diff; @@ -146,7 +145,7 @@ pub fn create_external_vector<'a, T>( schema: &str, ) -> io::Result> where - T: for<'b> Struct<'b>, + T: Struct, { // write schema let schema_name = format!("{}.schema", resource_name); @@ -225,46 +224,6 @@ pub fn create_archive( Ok(()) } -/// Describes a chunk of memory -#[doc(hidden)] -#[derive(Debug, Clone)] -pub struct MemoryDescriptor { - ptr: *const u8, - size: usize, -} - -impl Default for MemoryDescriptor { - #[inline] - fn default() -> MemoryDescriptor { - MemoryDescriptor { - ptr: ptr::null(), - size: 0, - } - } -} - -/// Describes a contiguous constant chunk of memory without tracking lifetime -/// Used to enabling caching files retrieved from ResourceStorage without -/// Sibling-Borrow woes -impl MemoryDescriptor { - /// Creates a new memory descriptor from a pointer and its size in bytes. - #[inline] - pub fn new(data: &[u8]) -> MemoryDescriptor { - MemoryDescriptor { - ptr: data.as_ptr(), - size: data.len(), - } - } - - /// Converts back to bytes (lifetime corresponds to the descriptor's) - /// Inherently unsafe, since there is no guarantee that the original buffer - /// is still alive - #[inline] - pub unsafe fn as_bytes(&self) -> &[u8] { - slice::from_raw_parts(self.ptr, self.size) - } -} - /// A handle to a resource for writing to it. /// /// Wraps a `Stream` returned by [`create_output_stream`]. diff --git a/flatdata-rs/lib/src/structbuf.rs b/flatdata-rs/lib/src/structbuf.rs deleted file mode 100644 index 185f8494..00000000 --- a/flatdata-rs/lib/src/structbuf.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Note: This module is called `structbuf` in contrast to `struct` in the C++ -// implementation, since Rust does not allow module names to be one of the -// language keywords. -use crate::{ - memory, - structs::{NoOverlap, RefFactory, Struct}, -}; - -use std::{fmt, marker}; - -/// A container holding a single flatdata struct in memory, and providing read -/// and write access to it. -/// -/// Used in combination with [`ArchiveBuilder`] to serialize single struct -/// resources, cf. [coappearances] example. -/// -/// A struct buffer derefs (const and mut) to a reference of the underlying -/// struct, therefore, struct getters and setters can be used directly on -/// buffer. -/// -/// # Examples -/// ``` flatdata -/// struct A { -/// x : u32 : 16; -/// y : u32 : 16; -/// } -/// -/// archive S { -/// data : A; -/// } -/// ``` -/// -/// ``` -/// use flatdata::{MemoryResourceStorage, Archive, ArchiveBuilder, StructBuf}; -/// use flatdata::test::{A, S, SBuilder}; -/// -/// let storage = MemoryResourceStorage::new("/root/structbuf"); -/// let builder = SBuilder::new(storage.clone()).expect("failed to create builder"); -/// let mut a = StructBuf::::new(); -/// a.get_mut().set_x(1); -/// a.get_mut().set_y(2); -/// builder.set_data(a.get()); -/// -/// println!("{:?}", storage); -/// let archive = S::open(storage).expect("failed to open"); -/// let view = archive.data(); -/// -/// assert_eq!(view.x(), 1); -/// assert_eq!(view.y(), 2); -/// ``` -/// -/// [`ArchiveBuilder`]: trait.ArchiveBuilder.html -/// [coappearances]: https://github.com/boxdot/flatdata-rs/blob/master/tests/coappearances_test.rs#L183 -pub struct StructBuf -where - T: RefFactory + NoOverlap, -{ - data: Vec, - _phantom: marker::PhantomData, -} - -impl StructBuf -where - T: RefFactory + NoOverlap, -{ - /// Creates an empty struct buffer. - /// - /// All fields are set to 0. - pub fn new() -> Self { - let data = vec![0; ::SIZE_IN_BYTES + memory::PADDING_SIZE]; - Self { - data, - _phantom: marker::PhantomData, - } - } - - /// Get the stored object - pub fn get(&self) -> ::Item { - ::create(&self.data) - } - - /// Get the mutable version of the stored object - pub fn get_mut(&mut self) -> ::ItemMut { - ::create_mut(&mut self.data) - } - - /// Returns a raw bytes representation of the buffer. - pub fn as_bytes(&self) -> &[u8] { - &self.data[0..::SIZE_IN_BYTES] - } -} - -impl fmt::Debug for StructBuf -where - T: RefFactory + NoOverlap, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "StructBuf {{ resource: {:?} }}", self.get()) - } -} - -impl Default for StructBuf -where - T: RefFactory + NoOverlap, -{ - fn default() -> Self { - Self::new() - } -} - -impl AsRef<[u8]> for StructBuf -where - T: RefFactory + NoOverlap, -{ - fn as_ref(&self) -> &[u8] { - self.as_bytes() - } -} - -#[cfg(test)] -#[allow(dead_code)] -mod test { - use super::*; - use crate::test::A; - - #[test] - fn test_new() { - let a = StructBuf::::new(); - let b = StructBuf::::default(); - assert_eq!(a.get(), b.get()); - } - - #[test] - fn test_setter_getter() { - let mut a = StructBuf::::new(); - a.get_mut().set_x(1); - a.get_mut().set_y(2); - assert_eq!(a.get().x(), 1); - assert_eq!(a.get().y(), 2); - a.get_mut().set_x(3); - assert_eq!(a.get().x(), 3); - assert_eq!(a.get().y(), 2); - a.get_mut().set_y(4); - assert_eq!(a.get().x(), 3); - assert_eq!(a.get().y(), 4); - let a_ref = a.get(); - assert_eq!(a_ref.x(), 3); - assert_eq!(a_ref.y(), 4); - } -} diff --git a/flatdata-rs/lib/src/structs.rs b/flatdata-rs/lib/src/structs.rs index 6cf4e108..e3d0445e 100644 --- a/flatdata-rs/lib/src/structs.rs +++ b/flatdata-rs/lib/src/structs.rs @@ -31,76 +31,39 @@ use std::fmt::Debug; #[doc(hidden)] pub use std::marker; -/// A type in flatdata used for reading data. -/// -/// Each struct reference in generated code implements this trait. -pub trait Ref: Clone + Copy + Debug + PartialEq {} - -/// A mutable type in flatdata used for writing data. -/// -/// Each struct reference in generated code has a corresponding type with suffix -/// `Mut` which implements this trait. -pub trait RefMut: Debug {} - /// 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<'a>: Clone { +pub trait Struct: 'static + Debug + Sized { + /// Create a new struct + /// Unsafety: If the struct is not self-contained, + /// and no subsequent struct in memory, then some + /// of its members must never be used + unsafe fn create_unchecked() -> Self; + /// Schema of the type. Used only for debug and inspection purposes. const SCHEMA: &'static str; /// 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; - - /// Item this factory will produce. - type Item: Ref; - - /// Creates a new item from a slice. - fn create(data: &'a [u8]) -> Self::Item; - - /// Item this factory will produce. - type ItemMut: RefMut; - - /// Creates a new item from a slice. - fn create_mut(data: &'a mut [u8]) -> Self::ItemMut; } -/// Shortcut trait for Structs that are able to produce references of any given -/// lifetime -/// -/// Equivalent to ```for<'a> Struct<'a>''' -pub trait RefFactory: for<'a> Struct<'a> {} -impl RefFactory for T where T: for<'a> Struct<'a> {} - /// Marks structs that can be used stand-alone, e.g. no range pub trait NoOverlap {} /// A specialized Struct factory producing Index items. /// Used primarily by the MultiVector/MultiArrayView. -pub trait IndexStruct<'a>: Struct<'a> { +pub trait IndexStruct: Struct { /// Provide getter for index - fn range(data: Self::Item) -> std::ops::Range; + fn range(&self) -> std::ops::Range; /// Provide setter for index - fn set_index(data: Self::ItemMut, value: usize); + fn set_index(&mut self, value: usize); } -/// Shortcut trait for IndexStructs that are able to produce references of any -/// given lifetime -/// -/// Equivalent to ```for<'a> IndexStruct<'a>''' -pub trait IndexRefFactory: for<'a> IndexStruct<'a> {} -impl IndexRefFactory for T where T: for<'a> IndexStruct<'a> {} - -/// A type in archive used as index of a `MultiArrayView`. -pub trait Index: Ref {} - -/// A type in archive used as mutable index of a `MultiVector`. -pub trait IndexMut: RefMut {} - /// Index specifying a variadic type of `MultiArrayView`. pub type TypeIndex = u8; @@ -115,15 +78,20 @@ pub trait VariadicRef: Clone + Debug + PartialEq { 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 { - /// Index type - type Index: IndexRefFactory; - /// Reader type type Item: VariadicRef; @@ -147,20 +115,25 @@ pub trait VariadicStruct<'a>: Clone { /// any given lifetime /// /// Equivalent to ```for<'a> VariadicStruct<'a>''' -pub trait VariadicRefFactory: for<'a> VariadicStruct<'a> {} -impl VariadicRefFactory for T where T: for<'a> VariadicStruct<'a> {} +pub trait VariadicRefFactory: for<'a> VariadicStruct<'a> + VariadicIndex {} + +impl VariadicRefFactory for T +where + T: for<'a> VariadicStruct<'a>, + T: VariadicIndex, +{ +} #[cfg(test)] mod test { use super::*; use crate::test::{A, R}; - use crate::StructBuf; #[test] fn test_debug() { - let a = StructBuf::::new(); + let a = A::new(); let output = format!("{:?}", a); - assert_eq!(output, "StructBuf { resource: A { x: 0, y: 0, e: Value } }"); + assert_eq!(output, "A { x: 0, y: 0, e: Value }"); } #[test] diff --git a/flatdata-rs/lib/src/test/test_generated.rs b/flatdata-rs/lib/src/test/test_generated.rs index 41b65286..7fae17ab 100644 --- a/flatdata-rs/lib/src/test/test_generated.rs +++ b/flatdata-rs/lib/src/test/test_generated.rs @@ -1,4 +1,5 @@ // Do not edit: This code was generated by flatdata's generator. +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod test { @@ -280,79 +281,105 @@ archive W "#; } } +}#[repr(transparent)] +#[derive(Clone)] +pub struct A { + data: [u8; 6], } -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`ARef`] for the read-only access, and -/// * [`AMut`] for the mutable access -/// -/// to the `A` data. -/// -/// [`ARef`]: struct.ARef.html -/// [`AMut`]: struct.AMut.html -#[derive(Clone, Debug)] -pub struct A {} -/// Read-only access to [`A`]. -/// -/// [`A`]: struct.A.html -#[derive(Clone, Copy)] -pub struct ARef<'a> { - data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl A { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 6]} + } } -impl<'a> crate::Struct<'a> for A -{ +impl crate::Struct for A { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 6]} + } + const SCHEMA: &'static str = schema::structs::A; const SIZE_IN_BYTES: usize = 6; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = ARef<'a>; +impl A { + pub fn new( ) -> Self { + Self{data : [0; 6]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 6]) -> &Self { + // Safety: This is safe since A is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = AMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 6]) -> &mut Self { + // Safety: This is safe since A is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, crate::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 6 { + assert_eq!(data.len(), 6); + return Err(crate::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 6]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, crate::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 6 { + assert_eq!(data.len(), 6); + return Err(crate::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 6]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 6] { + &self.data + } +} + +impl Default for A { + fn default( ) -> Self { + Self::new( ) } } impl crate::NoOverlap for A {} -impl<'a> ARef<'a> { +impl A { #[inline] pub fn x(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 16); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } #[inline] pub fn y(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 16, 16); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 16, 16); unsafe { std::mem::transmute::(value) } } #[inline] pub fn e(&self) -> super::test::E { - let value = flatdata_read_bytes!(u32, self.data, 32, 16); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 32, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for ARef<'a> { +impl std::fmt::Debug for A { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("A") .field("x", &self.x()) @@ -362,146 +389,127 @@ impl<'a> std::fmt::Debug for ARef<'a> { } } -impl<'a> std::cmp::PartialEq for ARef<'a> { +impl std::cmp::PartialEq for A { #[inline] fn eq(&self, other: &Self) -> bool { self.x() == other.x() && self.y() == other.y() && self.e() == other.e() } } -impl<'a> crate::Ref for ARef<'a> {} - -/// Mutable access to [`A`]. -/// -/// [`A`]: struct.A.html -pub struct AMut<'a> { - data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> AMut<'a> { +impl A { #[inline] - pub fn x(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_x(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 6) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 16) + flatdata_write_bytes!(u32; value, self.data, 0, 16) } #[inline] - pub fn y(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 16, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_y(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 6) - }; - flatdata_write_bytes!(u32; value, buffer, 16, 16) + flatdata_write_bytes!(u32; value, self.data, 16, 16) } #[inline] - pub fn e(&self) -> super::test::E { - let value = flatdata_read_bytes!(u32, self.data, 32, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_e(&mut self, value: super::test::E) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 6) - }; - flatdata_write_bytes!(u32; value, buffer, 32, 16) + flatdata_write_bytes!(u32; value, self.data, 32, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &ARef) { + pub fn fill_from(&mut self, other: &A) { self.set_x(other.x()); self.set_y(other.y()); self.set_e(other.e()); } } +#[repr(transparent)] +#[derive(Clone)] +pub struct B { + data: [u8; 2], +} -impl<'a> std::fmt::Debug for AMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - ARef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) +impl B { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} } } -impl<'a> crate::RefMut for AMut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`BRef`] for the read-only access, and -/// * [`BMut`] for the mutable access -/// -/// to the `B` data. -/// -/// [`BRef`]: struct.BRef.html -/// [`BMut`]: struct.BMut.html -#[derive(Clone, Debug)] -pub struct B {} - -/// Read-only access to [`B`]. -/// -/// [`B`]: struct.B.html -#[derive(Clone, Copy)] -pub struct BRef<'a> { - data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} +impl crate::Struct for B { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } -impl<'a> crate::Struct<'a> for B -{ const SCHEMA: &'static str = schema::structs::B; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = false; +} - type Item = BRef<'a>; +impl B { + pub fn new( ) -> Self { + Self{data : [0; 2]} + } - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array of matching size + pub fn from_bytes(data: &[u8; 2]) -> &Self { + // Safety: This is safe since B is repr(transparent) + unsafe{ std::mem::transmute( data ) } } - type ItemMut = BMut<'a>; + /// Create reference from byte array of matching size + pub fn from_bytes_mut(data: &mut [u8; 2]) -> &mut Self { + // Safety: This is safe since B is repr(transparent) + unsafe{ std::mem::transmute( data ) } + } - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } + /// Create reference from byte array + pub fn from_bytes_slice(data: &[u8]) -> Result<&Self, crate::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(crate::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *const [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes(unsafe { &*ptr })) + } + + /// Create reference from byte array + pub fn from_bytes_slice_mut(data: &mut [u8]) -> Result<&mut Self, crate::ResourceStorageError> { + // We cannot rely on TryFrom here, since it does not yet support > 33 bytes + if data.len() < 2 { + assert_eq!(data.len(), 2); + return Err(crate::ResourceStorageError::UnexpectedDataSize); + } + let ptr = data.as_ptr() as *mut [u8; 2]; + // Safety: We checked length before + Ok(Self::from_bytes_mut(unsafe { &mut *ptr })) + } + + pub fn as_bytes(&self) -> &[u8; 2] { + &self.data + } +} + +impl Default for B { + fn default( ) -> Self { + Self::new( ) } } impl crate::NoOverlap for B {} -impl<'a> BRef<'a> { +impl B { #[inline] pub fn id(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 16); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for BRef<'a> { +impl std::fmt::Debug for B { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("B") .field("id", &self.id()) @@ -509,129 +517,75 @@ impl<'a> std::fmt::Debug for BRef<'a> { } } -impl<'a> std::cmp::PartialEq for BRef<'a> { +impl std::cmp::PartialEq for B { #[inline] fn eq(&self, other: &Self) -> bool { self.id() == other.id() } } -impl<'a> crate::Ref for BRef<'a> {} - -/// Mutable access to [`B`]. -/// -/// [`B`]: struct.B.html -pub struct BMut<'a> { - data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> BMut<'a> { +impl B { #[inline] - pub fn id(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_id(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 16) + flatdata_write_bytes!(u32; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &BRef) { + pub fn fill_from(&mut self, other: &B) { self.set_id(other.id()); } } +#[repr(transparent)] +pub struct R { + data: [u8; 4], +} -impl<'a> std::fmt::Debug for BMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - BRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) +impl R { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 4]} } } -impl<'a> crate::RefMut for BMut<'a> {} - -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`RRef`] for the read-only access, and -/// * [`RMut`] for the mutable access -/// -/// to the `R` data. -/// -/// [`RRef`]: struct.RRef.html -/// [`RMut`]: struct.RMut.html -#[derive(Clone, Debug)] -pub struct R {} - -/// Read-only access to [`R`]. -/// -/// [`R`]: struct.R.html -#[derive(Clone, Copy)] -pub struct RRef<'a> { - data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, -} +impl crate::Struct for R { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 4]} + } -impl<'a> crate::Struct<'a> for R -{ const SCHEMA: &'static str = schema::structs::R; const SIZE_IN_BYTES: usize = 4; const IS_OVERLAPPING_WITH_NEXT : bool = true; - - type Item = RRef<'a>; - - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } - } - - type ItemMut = RMut<'a>; - - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } - } } -impl<'a> RRef<'a> { +impl R { /// First element of the range [`x`]. /// /// [`x`]: #method.x #[inline] pub fn first_x(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 16); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } #[inline] pub fn x(&self) -> std::ops::Range { - let start = flatdata_read_bytes!(u32, self.data, 0, 16); - let end = flatdata_read_bytes!(u32, self.data, 0 + 4 * 8, 16); + let start = flatdata_read_bytes!(u32, self.data.as_ptr(), 0, 16); + let end = flatdata_read_bytes!(u32, self.data.as_ptr(), 0 + 4 * 8, 16); start..end } #[inline] pub fn y(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 16, 16); + let value = flatdata_read_bytes!(u32, self.data.as_ptr(), 16, 16); unsafe { std::mem::transmute::(value) } } } -impl<'a> std::fmt::Debug for RRef<'a> { +impl std::fmt::Debug for R { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("R") .field("first_x", &self.first_x()) @@ -640,72 +594,36 @@ impl<'a> std::fmt::Debug for RRef<'a> { } } -impl<'a> std::cmp::PartialEq for RRef<'a> { +impl std::cmp::PartialEq for R { #[inline] fn eq(&self, other: &Self) -> bool { self.first_x() == other.first_x() && self.y() == other.y() } } -impl<'a> crate::Ref for RRef<'a> {} - -/// Mutable access to [`R`]. -/// -/// [`R`]: struct.R.html -pub struct RMut<'a> { - data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> RMut<'a> { +impl R { /// First element of the range [`x`]. /// /// [`x`]: struct.RRef.html#method.x #[inline] - pub fn first_x(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_first_x(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 0, 16) + flatdata_write_bytes!(u32; value, self.data, 0, 16) } #[inline] - pub fn y(&self) -> u32 { - let value = flatdata_read_bytes!(u32, self.data, 16, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_y(&mut self, value: u32) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 4) - }; - flatdata_write_bytes!(u32; value, buffer, 16, 16) + flatdata_write_bytes!(u32; value, self.data, 16, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &RRef) { + pub fn fill_from(&mut self, other: &R) { self.set_first_x(other.first_x()); self.set_y(other.y()); } } - -impl<'a> std::fmt::Debug for RMut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - RRef { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> crate::RefMut for RMut<'a> {} #[derive(Debug, PartialEq, Eq)] #[repr(u32)] pub enum E { @@ -721,27 +639,17 @@ impl crate::helper::Int for E { #[derive(Clone)] pub struct S { _storage: ::std::rc::Rc, - data: crate::MemoryDescriptor, + data : &'static super::test::A, } impl S { - fn read_resource( - storage: &dyn crate::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| crate::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn data(&self) -> ::Item - { - ::create(&unsafe {self.data.as_bytes()}) + pub fn data(&self) -> &super::test::A { + self.data } } @@ -761,9 +669,16 @@ impl crate::Archive for S { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use crate::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], crate::ResourceStorageError>| -> Result<&'static [u8], crate::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let data = Self::read_resource(&*storage, "data", schema::s::resources::DATA)?; + let resource = extend(storage.read("data", schema::s::resources::DATA)); + let data = resource.map(|x| super::test::A::from_bytes_slice(x))??; Ok(Self { _storage: storage, @@ -785,10 +700,9 @@ impl SBuilder { /// Stores [`data`] in the archive. /// /// [`data`]: struct.S.html#method.data - pub fn set_data(&self, resource: ::Item) -> ::std::io::Result<()> { - let data = unsafe { - ::std::slice::from_raw_parts(resource.data, ::SIZE_IN_BYTES) - }; + /// Stores [`data`] in the archive. + pub fn set_data(&self, resource: &super::test::A) -> ::std::io::Result<()> { + let data = resource.as_bytes(); self.storage.write("data", schema::s::resources::DATA, data) } @@ -812,27 +726,17 @@ impl crate::ArchiveBuilder for SBuilder { #[derive(Clone)] pub struct X { _storage: ::std::rc::Rc, - data: crate::MemoryDescriptor, + data : &'static [super::test::A], } impl X { - fn read_resource( - storage: &dyn crate::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| crate::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn data(&self) -> crate::ArrayView - { - crate::ArrayView::new(&unsafe {self.data.as_bytes()}) + pub fn data(&self) -> &[super::test::A] { + self.data } } @@ -852,9 +756,16 @@ impl crate::Archive for X { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use crate::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], crate::ResourceStorageError>| -> Result<&'static [u8], crate::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let data = Self::read_resource(&*storage, "data", schema::x::resources::DATA)?; + let resource = extend(storage.read("data", schema::x::resources::DATA)); + let data = resource.map(|x| <&[super::test::A]>::from_bytes(x))??; Ok(Self { _storage: storage, @@ -876,8 +787,9 @@ impl XBuilder { /// Stores [`data`] in the archive. /// /// [`data`]: struct.X.html#method.data - pub fn set_data(&self, vector: &crate::ArrayView) -> ::std::io::Result<()> { - self.storage.write("data", schema::x::resources::DATA, vector.as_ref()) + pub fn set_data(&self, vector: &[super::test::A]) -> ::std::io::Result<()> { + use crate::SliceExt; + self.storage.write("data", schema::x::resources::DATA, vector.as_bytes()) } /// Opens [`data`] in the archive for buffered writing. @@ -913,27 +825,17 @@ impl crate::ArchiveBuilder for XBuilder { #[derive(Clone)] pub struct Y { _storage: ::std::rc::Rc, - data: crate::MemoryDescriptor, + data : &'static [super::test::R], } impl Y { - fn read_resource( - storage: &dyn crate::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| crate::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn data(&self) -> crate::ArrayView - { - crate::ArrayView::new(&unsafe {self.data.as_bytes()}) + pub fn data(&self) -> &[super::test::R] { + self.data } } @@ -953,9 +855,16 @@ impl crate::Archive for Y { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use crate::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], crate::ResourceStorageError>| -> Result<&'static [u8], crate::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let data = Self::read_resource(&*storage, "data", schema::y::resources::DATA)?; + let resource = extend(storage.read("data", schema::y::resources::DATA)); + let data = resource.map(|x| <&[super::test::R]>::from_bytes(x))??; Ok(Self { _storage: storage, @@ -977,8 +886,9 @@ impl YBuilder { /// Stores [`data`] in the archive. /// /// [`data`]: struct.Y.html#method.data - pub fn set_data(&self, vector: &crate::ArrayView) -> ::std::io::Result<()> { - self.storage.write("data", schema::y::resources::DATA, vector.as_ref()) + pub fn set_data(&self, vector: &[super::test::R]) -> ::std::io::Result<()> { + use crate::SliceExt; + self.storage.write("data", schema::y::resources::DATA, vector.as_bytes()) } /// Opens [`data`] in the archive for buffered writing. @@ -1017,8 +927,8 @@ impl crate::ArchiveBuilder for YBuilder { #[derive(Clone, PartialEq)] pub enum AbRef<'a> { #[allow(missing_docs)] - A(>::Item), #[allow(missing_docs)] - B(>::Item),} + A(&'a super::test::A), #[allow(missing_docs)] + B(&'a super::test::B),} impl<'a> ::std::fmt::Debug for AbRef<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -1033,8 +943,8 @@ impl<'a> crate::VariadicRef for AbRef<'a> { #[inline] fn size_in_bytes(&self) -> usize { match *self { - AbRef::A(_) => >::SIZE_IN_BYTES, - AbRef::B(_) => >::SIZE_IN_BYTES, + AbRef::A(_) => ::SIZE_IN_BYTES, + AbRef::B(_) => ::SIZE_IN_BYTES, } } } @@ -1054,27 +964,25 @@ impl<'a> AbBuilder<'a> { /// /// [`A`]: struct.A.html #[inline] - pub fn add_a<'b>(&'b mut self) -> >::ItemMut { + pub fn add_a<'b>(&'b mut self) -> &'b mut super::test::A { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - crate::PADDING_SIZE] = 0; - >::create_mut( - &mut self.data[1 + old_len - crate::PADDING_SIZE..] - ) + self.data[old_len] = 0; + let slice = &mut self.data[1 + old_len..]; + super::test::A::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::test::A from slice") } /// Adds data of the type [`B`] to the bucket. /// /// [`B`]: struct.B.html #[inline] - pub fn add_b<'b>(&'b mut self) -> >::ItemMut { + pub fn add_b<'b>(&'b mut self) -> &'b mut super::test::B { let old_len = self.data.len(); - let increment = 1 + >::SIZE_IN_BYTES; + let increment = 1 + ::SIZE_IN_BYTES; self.data.resize(old_len + increment, 0); - self.data[old_len - crate::PADDING_SIZE] = 1; - >::create_mut( - &mut self.data[1 + old_len - crate::PADDING_SIZE..] - ) + self.data[old_len] = 1; + let slice = &mut self.data[1 + old_len..]; + super::test::B::from_bytes_slice_mut(slice).expect("Logic error: Cannot create super::test::B from slice") } } @@ -1101,17 +1009,19 @@ impl<'a> AbBuilder<'a> { #[derive(Clone)] pub struct Ab {} -impl<'a> crate::VariadicStruct<'a> for Ab { +impl crate::VariadicIndex for Ab { type Index = super::_builtin::multivector::IndexType16; +} +impl<'a> crate::VariadicStruct<'a> for Ab { type Item = AbRef<'a>; #[inline] fn create(index: crate::TypeIndex, data: &'a [u8]) -> Self::Item { match index { - 0 => AbRef::A(>::create(data)), - 1 => AbRef::B(>::create(data)), + 0 => AbRef::A(super::test::A::from_bytes_slice(&data).expect("Corrupted data")), + 1 => AbRef::B(super::test::B::from_bytes_slice(&data).expect("Corrupted data")), _ => panic!("invalid type index {} for variadic type AbRef", index), } } @@ -1128,30 +1038,17 @@ impl<'a> crate::VariadicStruct<'a> for Ab { #[derive(Clone)] pub struct Z { _storage: ::std::rc::Rc, - ab: (crate::MemoryDescriptor, crate::MemoryDescriptor), + ab : crate::MultiArrayView<'static, Ab>, } impl Z { - fn read_resource( - storage: &dyn crate::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| crate::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] - pub fn ab(&self) -> crate::MultiArrayView - { - crate::MultiArrayView::new( - crate::ArrayView::new(&unsafe {self.ab.0.as_bytes()}), - &unsafe {self.ab.1.as_bytes()}, - ) + pub fn ab(&self) -> &crate::MultiArrayView { + &self.ab } } @@ -1171,12 +1068,29 @@ impl crate::Archive for Z { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use crate::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], crate::ResourceStorageError>| -> Result<&'static [u8], crate::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; let ab = { let index_schema = &format!("index({})", schema::z::resources::AB); - let index = Self::read_resource(&*storage, "ab_index", &index_schema)?; - let data = Self::read_resource(&*storage, "ab", schema::z::resources::AB)?; (index, data) + let index = extend(storage.read("ab_index", &index_schema)); + let data = extend(storage.read("ab", schema::z::resources::AB)); + let result = match (index, data) { + (Ok(index), Ok(data)) => { + Ok(crate::MultiArrayView::new( + <&[super::_builtin::multivector::IndexType16]>::from_bytes(index)?, + data + )) + } + (Ok(_), Err(x)) | (Err(x), Ok(_)) => {return Err(x);} + (Err(x), Err(_)) => Err(x), + }; + result? }; Ok(Self { @@ -1228,26 +1142,17 @@ impl crate::ArchiveBuilder for ZBuilder { #[derive(Clone)] pub struct W { _storage: ::std::rc::Rc, - blob: crate::MemoryDescriptor, + blob : crate::RawData<'static>, } impl W { - fn read_resource( - storage: &dyn crate::ResourceStorage, - name: &str, - schema: &str, - ) -> Result - { - storage.read(name, schema).map(|x| crate::MemoryDescriptor::new(&x)) - } - fn signature_name(archive_name: &str) -> String { format!("{}.archive", archive_name) } #[inline] pub fn blob(&self) -> crate::RawData { - crate::RawData::new(unsafe {self.blob.as_bytes()}) + self.blob } } @@ -1267,9 +1172,16 @@ impl crate::Archive for W { fn open(storage: ::std::rc::Rc) -> ::std::result::Result { + #[allow(unused_imports)] + use crate::SliceExt; + // extend lifetime since Rust cannot know that we reference a cache here + #[allow(unused_variables)] + let extend = |x : Result<&[u8], crate::ResourceStorageError>| -> Result<&'static [u8], crate::ResourceStorageError> {x.map(|x| unsafe{std::mem::transmute(x)})}; + storage.read(&Self::signature_name(Self::NAME), Self::SCHEMA)?; - let blob = Self::read_resource(&*storage, "blob", schema::w::resources::BLOB)?; + let resource = extend(storage.read("blob", schema::w::resources::BLOB)); + let blob = resource.map(|x| crate::RawData::new(x))?; Ok(Self { _storage: storage, @@ -1311,9 +1223,11 @@ impl crate::ArchiveBuilder for WBuilder { } +#[cfg_attr(rustfmt, rustfmt_skip)] #[doc(hidden)] pub mod _builtin { +#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(missing_docs)] pub mod multivector { @@ -1324,77 +1238,50 @@ pub const INDEX_TYPE16: &str = r#""#; } } - /// Builtin type to for MultiVector index -/// -/// ## Access pattern -/// -/// This structure is used as a template parameter in containers. -/// It does not contain any data, instead it references -/// -/// * [`IndexType16Ref`] for the read-only access, and -/// * [`IndexType16Mut`] for the mutable access -/// -/// to the `IndexType16` data. -/// -/// [`IndexType16Ref`]: struct.IndexType16Ref.html -/// [`IndexType16Mut`]: struct.IndexType16Mut.html -#[derive(Clone, Debug)] -pub struct IndexType16 {} +#[repr(transparent)] +pub struct IndexType16 { + data: [u8; 2], +} -/// Read-only access to [`IndexType16`]. -/// -/// [`IndexType16`]: struct.IndexType16.html -#[derive(Clone, Copy)] -pub struct IndexType16Ref<'a> { - data: *const u8, - _phantom: std::marker::PhantomData<&'a u8>, +impl IndexType16 { + /// Unsafe since the struct might not be self-contained + pub unsafe fn new_unchecked( ) -> Self { + Self{data : [0; 2]} + } } -impl<'a> crate::Struct<'a> for IndexType16 -{ +impl crate::Struct for IndexType16 { + unsafe fn create_unchecked( ) -> Self { + Self{data : [0; 2]} + } + const SCHEMA: &'static str = schema::structs::INDEX_TYPE16; const SIZE_IN_BYTES: usize = 2; const IS_OVERLAPPING_WITH_NEXT : bool = true; - - type Item = IndexType16Ref<'a>; - - #[inline] - fn create(data : &'a[u8]) -> Self::Item - { - Self::Item { data : data.as_ptr(), _phantom : std::marker::PhantomData } - } - - type ItemMut = IndexType16Mut<'a>; - - #[inline] - fn create_mut(data: &'a mut[u8]) -> Self::ItemMut - { - Self::ItemMut { data : data.as_mut_ptr(), _phantom : std::marker::PhantomData } - } } -impl<'a> IndexType16Ref<'a> { +impl IndexType16 { /// First element of the range [`range`]. /// /// [`range`]: #method.range #[inline] pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 16); + let value = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 16); unsafe { std::mem::transmute::(value) } } #[inline] pub fn range(&self) -> std::ops::Range { - let start = flatdata_read_bytes!(u64, self.data, 0, 16); - let end = flatdata_read_bytes!(u64, self.data, 0 + 2 * 8, 16); + let start = flatdata_read_bytes!(u64, self.data.as_ptr(), 0, 16); + let end = flatdata_read_bytes!(u64, self.data.as_ptr(), 0 + 2 * 8, 16); start..end } } -impl<'a> std::fmt::Debug for IndexType16Ref<'a> { +impl std::fmt::Debug for IndexType16 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("IndexType16") .field("value", &self.value()) @@ -1402,67 +1289,40 @@ impl<'a> std::fmt::Debug for IndexType16Ref<'a> { } } -impl<'a> std::cmp::PartialEq for IndexType16Ref<'a> { +impl std::cmp::PartialEq for IndexType16 { #[inline] fn eq(&self, other: &Self) -> bool { self.value() == other.value() } } -impl<'a> crate::Ref for IndexType16Ref<'a> {} - -/// Mutable access to [`IndexType16`]. -/// -/// [`IndexType16`]: struct.IndexType16.html -pub struct IndexType16Mut<'a> { - data: *mut u8, - _phantom: std::marker::PhantomData<&'a u8>, -} - -impl<'a> IndexType16Mut<'a> { +impl IndexType16 { /// First element of the range [`range`]. /// /// [`range`]: struct.IndexType16Ref.html#method.range #[inline] - pub fn value(&self) -> u64 { - let value = flatdata_read_bytes!(u64, self.data, 0, 16); - unsafe { std::mem::transmute::(value) } - } - #[allow(missing_docs)] - #[inline] pub fn set_value(&mut self, value: u64) { - let buffer = unsafe { - std::slice::from_raw_parts_mut(self.data, 2) - }; - flatdata_write_bytes!(u64; value, buffer, 0, 16) + flatdata_write_bytes!(u64; value, self.data, 0, 16) } /// Copies the data from `other` into this struct. #[inline] - pub fn fill_from(&mut self, other: &IndexType16Ref) { + pub fn fill_from(&mut self, other: &IndexType16) { self.set_value(other.value()); } } -impl<'a> std::fmt::Debug for IndexType16Mut<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - IndexType16Ref { data : self.data, _phantom : std::marker::PhantomData }.fmt( f ) - } -} - -impl<'a> crate::RefMut for IndexType16Mut<'a> {} - -impl<'a> crate::IndexStruct<'a> for IndexType16 { +impl crate::IndexStruct for IndexType16 { #[inline] - fn range(data: Self::Item) -> std::ops::Range { - let range = data.range(); + fn range(&self) -> std::ops::Range { + let range = self.range(); range.start as usize..range.end as usize } #[inline] - fn set_index(mut data: Self::ItemMut, value: usize) { - data.set_value(value as u64); + fn set_index(&mut self, value: usize) { + self.set_value(value as u64); } } diff --git a/flatdata-rs/lib/src/vector.rs b/flatdata-rs/lib/src/vector.rs index 10ab55fb..dd66b0ae 100644 --- a/flatdata-rs/lib/src/vector.rs +++ b/flatdata-rs/lib/src/vector.rs @@ -1,12 +1,8 @@ -use crate::{ - arrayview::{debug_format, ArrayView}, - error::ResourceStorageError, - structs::{RefFactory, Struct}, -}; +use crate::{error::ResourceStorageError, structs::Struct, SliceExt}; -use crate::{memory, storage::ResourceHandle}; +use crate::storage::ResourceHandle; -use std::{borrow::BorrowMut, fmt, io, marker}; +use std::{borrow::BorrowMut, fmt, io}; /// A container holding a contiguous sequence of flatdata structs of the same /// type `T` in memory, and providing read and write access to it. @@ -53,65 +49,45 @@ use std::{borrow::BorrowMut, fmt, io, marker}; /// /// let archive = X::open(storage).expect("failed to open"); /// let view = archive.data(); -/// assert_eq!(view.at(1).x(), 3); +/// assert_eq!(view[1].x(), 3); /// ``` /// /// [`ExternalVector`]: struct.ExternalVector.html /// [`as_view`]: #method.as_view -#[derive(Clone)] pub struct Vector where - T: RefFactory, + T: Struct, { - data: Vec, - _phantom: marker::PhantomData, + data: Vec, } impl Vector where - T: RefFactory, + T: Struct, { - fn padding() -> usize { - if ::IS_OVERLAPPING_WITH_NEXT { - ::SIZE_IN_BYTES + memory::PADDING_SIZE - } else { - memory::PADDING_SIZE - } - } /// Creates an empty `Vector`. #[inline] pub fn new() -> Self { Self::with_len(0) } + /// Resets the 'Vector' to its initial empty state + #[inline] + pub fn clear(&mut self) { + self.data.clear(); + self.data.push(unsafe { T::create_unchecked() }); + } + /// Creates a `Vector` with `len` many elements. /// /// `T`'s fields are all filled with zeroes. #[inline] pub fn with_len(len: usize) -> Self { - let size = Self::calc_size(len); - Self { - data: vec![0; size], - _phantom: marker::PhantomData, + let mut data = Vec::with_capacity(len + 1); + for _ in 0..=len { + data.push(unsafe { T::create_unchecked() }); } - } - - /// Size of the vector in bytes. - #[inline] - pub fn size_in_bytes(&self) -> usize { - self.data.len() - Self::padding() - } - - /// Number of elements in the vector. - #[inline] - pub fn len(&self) -> usize { - self.size_in_bytes() / ::SIZE_IN_BYTES - } - - /// Returns `true` if the vector has a length 0. - #[inline] - pub fn is_empty(&self) -> bool { - self.len() == 0 + Self { data } } /// Reserves capacity for at least `additional` more elements to be @@ -121,57 +97,54 @@ where /// if capacity is already sufficient. #[inline] pub fn reserve(&mut self, additional: usize) { - let additional_bytes = Self::calc_size(self.len() + additional) - self.size_in_bytes(); - self.data.reserve(additional_bytes) - } - - /// Returns an `ArrayView` to this vector. - #[inline] - pub fn as_view(&self) -> ArrayView { - ArrayView::new(&self.data[..self.size_in_bytes()]) + self.data.reserve(self.data.len() + additional) } - /// Returns the contents of this vector as slice of bytes. + /// Returns a slice for the vector contents. Hides sentinels in case T IS_OVERLAPPING_WITH_NEXT #[inline] - pub fn as_bytes(&self) -> &[u8] { - &self.data[..self.size_in_bytes()] + pub fn as_view(&self) -> &[T] { + if T::IS_OVERLAPPING_WITH_NEXT { + &self.data[0..self.data.len().saturating_sub(2)] + } else { + &self.data[0..self.data.len() - 1] + } } /// Appends an element to the end of this vector and returns a mutable /// handle to it. #[inline] - pub fn grow(&mut self) -> ::ItemMut { - let old_size = self.data.len(); - self.data.resize(old_size + ::SIZE_IN_BYTES, 0); - let last_index = self.len() - 1; - T::create_mut(&mut self.data[last_index * ::SIZE_IN_BYTES..]) + pub fn grow(&mut self) -> &mut T { + let next = self.len(); + self.data.push(unsafe { T::create_unchecked() }); + &mut self.data[next] } +} - /// Return an accessor handle to the element at position `index` in the - /// vector. - #[inline] - pub fn at(&self, index: usize) -> ::Item { - T::create(&self.data[index * ::SIZE_IN_BYTES..]) - } +impl std::ops::Deref for Vector +where + T: Struct, +{ + type Target = [T]; - /// Return a mutable handle to the element at position `index` in the - /// vector. - #[inline] - pub fn at_mut(&mut self, index: usize) -> ::ItemMut { - T::create_mut(&mut self.data[index * ::SIZE_IN_BYTES..]) + fn deref(&self) -> &[T] { + let len = self.data.len() - 1; + &self.data[0..len] } +} - /// Calculates size in bytes (with padding) needed to store `len` many - /// elements. - #[inline] - fn calc_size(len: usize) -> usize { - len * ::SIZE_IN_BYTES + Self::padding() +impl std::ops::DerefMut for Vector +where + T: Struct, +{ + fn deref_mut(&mut self) -> &mut [T] { + let len = self.data.len() - 1; + &mut self.data[0..len] } } impl Default for Vector where - T: RefFactory, + T: Struct, { /// Creates an empty `Vector`. fn default() -> Self { @@ -179,25 +152,12 @@ where } } -impl AsRef<[u8]> for Vector -where - T: RefFactory, -{ - /// Returns the content of this vector as slice of bytes. Equivalent to - /// [`as_bytes`]. - /// - /// [`as_bytes`]: #method.as_bytes - fn as_ref(&self) -> &[u8] { - self.as_bytes() - } -} - impl fmt::Debug for Vector where - T: RefFactory, + T: Struct + std::fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - debug_format("Vector", self.as_view().iter(), f) + self.as_view().fmt(f) } } @@ -244,38 +204,36 @@ where /// /// // data can also be inspected directly after closing /// assert_eq!(view.len(), 2); -/// assert_eq!(view.at(0).x(), 0); -/// assert_eq!(view.at(0).y(), 1); +/// assert_eq!(view[0].x(), 0); +/// assert_eq!(view[0].y(), 1); /// } /// /// let archive = X::open(storage).expect("failed to open"); /// let view = archive.data(); -/// assert_eq!(view.at(1).x(), 2); -/// assert_eq!(view.at(1).y(), 3); +/// assert_eq!(view[1].x(), 2); +/// assert_eq!(view[1].y(), 3); /// ``` /// /// [`grow`]: #method.grow pub struct ExternalVector<'a, T> where - T: RefFactory, + T: Struct, { - data: Vec, + data: Vector, len: usize, resource_handle: ResourceHandle<'a>, - _phantom: marker::PhantomData, } impl<'a, T> ExternalVector<'a, T> where - T: RefFactory, + T: Struct, { /// Creates an empty `ExternalVector` in the given resource storage. pub fn new(resource_handle: ResourceHandle<'a>) -> Self { Self { - data: vec![0; memory::PADDING_SIZE], + data: Vector::new(), len: 0, resource_handle, - _phantom: marker::PhantomData, } } @@ -296,26 +254,20 @@ where /// may fail due to different IO reasons. /// /// [`flush`]: #method.flush - pub fn grow(&mut self) -> io::Result<::ItemMut> { - if self.data.len() > 1024 * 1024 * 32 { + pub fn grow(&mut self) -> io::Result<&mut T> { + if self.data.as_view().as_bytes().len() > 1024 * 1024 * 32 { self.flush()?; } - let old_size = self.data.len(); - self.data.resize(old_size + ::SIZE_IN_BYTES, 0); self.len += 1; - Ok(T::create_mut( - &mut self.data[old_size - memory::PADDING_SIZE..], - )) + Ok(self.data.grow()) } /// Flushes the not yet flushed content in this vector to storage. fn flush(&mut self) -> io::Result<()> { self.resource_handle .borrow_mut() - .write(&self.data[..self.data.len() - memory::PADDING_SIZE])?; - self.data.resize(0, 0); - - self.data.resize(memory::PADDING_SIZE, 0); + .write(&self.data.as_view().as_bytes())?; + self.data.clear(); Ok(()) } @@ -323,19 +275,21 @@ where /// finalizes the data inside the storage. /// /// An external vector *must* be closed - pub fn close(mut self) -> Result, ResourceStorageError> { - self.flush().map_err(|e| { - ResourceStorageError::from_io_error(e, self.resource_handle.name().into()) - })?; + pub fn close(mut self) -> Result<&'a [T], ResourceStorageError> { + if self.data.len() > 0 || self.len == 0 { + self.flush().map_err(|e| { + ResourceStorageError::from_io_error(e, self.resource_handle.name().into()) + })?; + } self.resource_handle .close() - .map(|data| ArrayView::new(data)) + .map(|data| <&[T]>::from_bytes(data).expect("Corrupted data")) } } impl fmt::Debug for ExternalVector<'_, T> where - T: RefFactory, + T: Struct, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ExternalVector {{ len: {} }}", self.len()) @@ -359,13 +313,13 @@ mod tests { #[test] fn test_vector_range() { let mut v: Vector = Vector::with_len(3); - v.at_mut(0).set_first_x(10); - v.at_mut(1).set_first_x(20); - v.at_mut(2).set_first_x(30); + v[0].set_first_x(10); + v[1].set_first_x(20); + v[2].set_first_x(30); - assert_eq!(v.at(0).x(), 10..20); - assert_eq!(v.at(1).x(), 20..30); - assert_eq!(v.at(2).x(), 30..0); + assert_eq!(v[0].x(), 10..20); + assert_eq!(v[1].x(), 20..30); + assert_eq!(v[2].x(), 30..0); } #[test] @@ -373,23 +327,23 @@ mod tests { let mut v: Vector = Vector::with_len(2); assert_eq!(v.len(), 2); { - let mut a = v.at_mut(0); + let a = &mut v[0]; a.set_x(1); a.set_y(2); assert_eq!(a.x(), 1); assert_eq!(a.y(), 2); } { - let mut b = v.at_mut(1); + let b = &mut v[1]; b.set_x(3); b.set_y(4); assert_eq!(b.x(), 3); assert_eq!(b.y(), 4); } - let a = v.at(0); + let a = &mut v[0]; assert_eq!(a.x(), 1); assert_eq!(a.y(), 2); - let b = v.at(1); + let b = &mut v[1]; assert_eq!(b.x(), 3); assert_eq!(b.y(), 4); } @@ -399,14 +353,14 @@ mod tests { let mut v: Vector = Vector::with_len(1); assert_eq!(v.len(), 1); { - let mut a = v.at_mut(0); + let a = &mut v[0]; a.set_x(1); assert_eq!(a.x(), 1); a.set_y(2); assert_eq!(a.y(), 2); } let view = v.as_view(); - let a = view.at(0); + let a = &view[0]; assert_eq!(a.x(), 1); assert_eq!(a.y(), 2); } @@ -416,14 +370,14 @@ mod tests { let mut v: Vector = Vector::with_len(1); assert_eq!(v.len(), 1); { - let mut a = v.at_mut(0); + let a = &mut v[0]; a.set_x(1); a.set_y(2); assert_eq!(a.x(), 1); assert_eq!(a.y(), 2); } { - let mut b = v.grow(); + let b = v.grow(); b.set_x(3); b.set_y(4); assert_eq!(b.x(), 3); @@ -431,10 +385,10 @@ mod tests { } { assert_eq!(v.len(), 2); - let a = &v.at(0); + let a = &v[0]; assert_eq!(a.x(), 1); assert_eq!(a.y(), 2); - let b = &v.at(1); + let b = &v[1]; assert_eq!(b.x(), 3); assert_eq!(b.y(), 4); } diff --git a/flatdata-rs/tests/coappearances/src/lib.rs b/flatdata-rs/tests/coappearances/src/lib.rs index f893d880..ef5f6d04 100644 --- a/flatdata-rs/tests/coappearances/src/lib.rs +++ b/flatdata-rs/tests/coappearances/src/lib.rs @@ -37,31 +37,30 @@ fn read_and_validate_coappearances() -> Result<(), std::str::Utf8Error> { assert_eq!(g.chapters().len(), num_chapters); assert_eq!( - g.strings().substring(vertices.at(0).name_ref() as usize)?, + g.strings().substring(vertices[0].name_ref() as usize)?, "Annushka" ); assert_eq!( - g.strings().substring(vertices.at(3).name_ref() as usize)?, + g.strings().substring(vertices[3].name_ref() as usize)?, "Anna Arkadyevna Karenina" ); - let e0 = edges.at(0); + let e0 = &edges[0]; assert_eq!( g.strings() - .substring(vertices.at(e0.a_ref() as usize).name_ref() as usize)?, + .substring(vertices[e0.a_ref() as usize].name_ref() as usize)?, "Annushka" ); assert_eq!( g.strings() - .substring(vertices.at(e0.b_ref() as usize).name_ref() as usize)?, + .substring(vertices[e0.b_ref() as usize].name_ref() as usize)?, "Anna Arkadyevna Karenina" ); - let validate_chapters = |edge_ref, expected| { - let chapters_range = edges.at(edge_ref).chapters_range(); - let e_chapters: Vec = g - .chapters() - .slice(chapters_range.start as usize..chapters_range.end as usize) + let validate_chapters = |edge_ref: usize, expected| { + let chapters_range = edges[edge_ref].chapters_range(); + let e_chapters: Vec = g.chapters() + [chapters_range.start as usize..chapters_range.end as usize] .iter() .map(|ch| format!("{}.{}", ch.major(), ch.minor())) .collect(); @@ -87,7 +86,7 @@ fn read_and_validate_coappearances() -> Result<(), std::str::Utf8Error> { assert_eq!(g.strings().substring(data.kind_ref() as usize)?, "maid"); assert_eq!( g.strings() - .substring(vertices.at(data.to_ref() as usize).name_ref() as usize)?, + .substring(vertices[data.to_ref() as usize].name_ref() as usize)?, "Anna Arkadyevna Karenina" ); } @@ -104,7 +103,7 @@ fn read_and_validate_coappearances() -> Result<(), std::str::Utf8Error> { ); assert_eq!( g.strings() - .substring(vertices.at(data.to_ref() as usize).name_ref() as usize)?, + .substring(vertices[data.to_ref() as usize].name_ref() as usize)?, "Konstantin Dmitrievitch Levin" ); } @@ -121,7 +120,7 @@ fn read_and_validate_coappearances() -> Result<(), std::str::Utf8Error> { ); assert_eq!( g.strings() - .substring(vertices.at(data.to_ref() as usize).name_ref() as usize)?, + .substring(vertices[data.to_ref() as usize].name_ref() as usize)?, "Count Alexey Kirillovitch Vronsky" ); } @@ -139,7 +138,13 @@ fn check_files(name_a: &path::Path, name_b: &path::Path) { let mut buf_b = Vec::new(); fb.read_to_end(&mut buf_b).unwrap(); - assert_eq!(buf_a, buf_b); + assert_eq!( + buf_a, + buf_b, + "{}, vs {}", + name_a.display(), + name_b.display() + ); } fn check_resource(from: &path::PathBuf, to: &path::PathBuf, resource_name: &str) { @@ -170,15 +175,15 @@ fn copy_coappearances_archive( let gb = coappearances::GraphBuilder::new(storage).expect("could not create archive"); // copy data - let mut meta = flatdata::StructBuf::::new(); - meta.get_mut().fill_from(&g.meta()); - gb.set_meta(meta.get()).expect("set_meta failed"); + let mut meta = coappearances::Meta::new(); + meta.fill_from(&g.meta()); + gb.set_meta(&meta).expect("set_meta failed"); check_resource(&source_archive_path, &archive_path, "meta"); { let mut vertices = gb.start_vertices().expect("start_vertices failed"); for v in g.vertices().iter() { - let mut w = vertices.grow().expect("grow failed"); + let w = vertices.grow().expect("grow failed"); w.fill_from(&v); } vertices.close().expect("close failed"); @@ -190,8 +195,8 @@ fn copy_coappearances_archive( edges.grow().fill_from(&e); } // add final sentinel - let mut sentinel = edges.grow(); - sentinel.set_first_chapter_ref(g.edges().at(g.edges().len() - 1).chapters_range().end); + let sentinel = edges.grow(); + sentinel.set_first_chapter_ref(g.edges()[g.edges().len() - 1].chapters_range().end); sentinel.set_a_ref(std::u16::MAX as u32); sentinel.set_b_ref(std::u16::MAX as u32); gb.set_edges(&edges.as_view()).expect("set_edges failed"); @@ -207,19 +212,19 @@ fn copy_coappearances_archive( for element in item { match element { coappearances::VerticesDataRef::Nickname(ref nickname) => { - let mut new_element = new_item.add_nickname(); + let new_element = new_item.add_nickname(); new_element.fill_from(nickname); } coappearances::VerticesDataRef::Description(ref desc) => { - let mut new_element = new_item.add_description(); + let new_element = new_item.add_description(); new_element.fill_from(desc); } coappearances::VerticesDataRef::UnaryRelation(ref rel) => { - let mut new_element = new_item.add_unary_relation(); + let new_element = new_item.add_unary_relation(); new_element.fill_from(rel); } coappearances::VerticesDataRef::BinaryRelation(ref rel) => { - let mut new_element = new_item.add_binary_relation(); + let new_element = new_item.add_binary_relation(); new_element.fill_from(rel); } } @@ -274,18 +279,15 @@ fn read_write_statistics_subarchive() { ); let builder = gb.statistics().expect("statistics failed"); - let mut inv_buf = flatdata::StructBuf::::new(); + let mut inv = coappearances::Invariants::new(); { - let mut inv = inv_buf.get_mut(); inv.set_max_degree(71); inv.set_max_degree_ref(46); inv.set_min_degree(1); inv.set_min_degree_ref(9); inv.set_num_connected_components(1); } - builder - .set_invariants(inv_buf.get()) - .expect("set_invariants failed"); + builder.set_invariants(&inv).expect("set_invariants failed"); let degrees = vec![ 4, 11, 25, 43, 3, 3, 4, 7, 2, 1, 1, 1, 12, 3, 1, 4, 8, 2, 6, 40, 2, 5, 2, 1, 1, 6, 3, 16, @@ -318,8 +320,8 @@ fn read_write_statistics_subarchive() { ); for i in 0..orig_stats.vertex_degrees().len() { assert_eq!( - orig_stats.vertex_degrees().at(i), - copy_stats.vertex_degrees().at(i) + orig_stats.vertex_degrees()[i], + copy_stats.vertex_degrees()[i] ); } } diff --git a/flatdata-rs/tests/features/src/archives/ranges.rs b/flatdata-rs/tests/features/src/archives/ranges.rs index 5ff26a93..371afc25 100644 --- a/flatdata-rs/tests/features/src/archives/ranges.rs +++ b/flatdata-rs/tests/features/src/archives/ranges.rs @@ -11,7 +11,7 @@ fn test() { let mut data = flatdata::Vector::::new(); for x in 10..600 { - let mut next = data.grow(); + let next = data.grow(); next.set_x(x); next.set_first_y(x as u32 * 10); } @@ -26,9 +26,9 @@ fn test() { let data = archive.data(); assert_eq!(599 - 10, data.len()); for x in (10..599).enumerate() { - assert_eq!(data.at(x.0).x(), x.1); + assert_eq!(data[x.0].x(), x.1); assert_eq!( - data.at(x.0).y_range(), + data[x.0].y_range(), (x.1 as u32 * 10..(x.1 as u32 + 1) * 10) ); } diff --git a/flatdata-rs/tests/features/src/archives/struct_in_archive.rs b/flatdata-rs/tests/features/src/archives/struct_in_archive.rs index 908e51d9..3e638a6a 100644 --- a/flatdata-rs/tests/features/src/archives/struct_in_archive.rs +++ b/flatdata-rs/tests/features/src/archives/struct_in_archive.rs @@ -10,15 +10,15 @@ fn test() { let storage = flatdata::MemoryResourceStorage::new("/my_test"); let builder = n::ABuilder::new(storage.clone()).expect("Failed to create builder"); - let mut data = flatdata::StructBuf::::new(); - data.get_mut().set_x(14); - builder.set_data(data.get()).expect("Failed to set data"); + let mut data = n::S::new(); + data.set_x(14); + builder.set_data(&data).expect("Failed to set data"); if set_optional { - let mut optional_data = flatdata::StructBuf::::new(); - optional_data.get_mut().set_x(16); + let mut optional_data = n::S::new(); + optional_data.set_x(16); builder - .set_optional_data(optional_data.get()) + .set_optional_data(&optional_data) .expect("Failed to set optional data"); } diff --git a/flatdata-rs/tests/features/src/archives/vector.rs b/flatdata-rs/tests/features/src/archives/vector.rs index 696111ad..7a74ee29 100644 --- a/flatdata-rs/tests/features/src/archives/vector.rs +++ b/flatdata-rs/tests/features/src/archives/vector.rs @@ -37,12 +37,12 @@ fn test() { let archive = n::A::open(storage).expect("Failed to open archive"); let data = archive.data(); for x in (10..600).enumerate() { - assert_eq!(data.at(x.0).x(), x.1); + assert_eq!(data[x.0].x(), x.1); } if set_optional { let data = archive.optional_data().expect("Optional data not found"); for x in (10..600).enumerate() { - assert_eq!(data.at(x.0).x(), x.1); + assert_eq!(data[x.0].x(), x.1); } } } diff --git a/flatdata-rs/tests/features/src/enums/namespaces.rs b/flatdata-rs/tests/features/src/enums/namespaces.rs index 9c4db005..ef4bebb0 100644 --- a/flatdata-rs/tests/features/src/enums/namespaces.rs +++ b/flatdata-rs/tests/features/src/enums/namespaces.rs @@ -7,9 +7,9 @@ fn values_in_namespaces() { assert_eq!(a::Bar::Value as i32, 0); assert_eq!(b::Bar::Value as i32, 0); - let a_buf = flatdata::StructBuf::::new(); - assert_eq!(a_buf.get().f(), a::Bar::Value); + let a = n::Foo::new(); + assert_eq!(a.f(), a::Bar::Value); - let b_buf = flatdata::StructBuf::::new(); - assert_eq!(b_buf.get().f(), b::Bar::Value); + let b = m::Foo::new(); + assert_eq!(b.f(), b::Bar::Value); } diff --git a/flatdata-rs/tests/features/src/enums/structs.rs b/flatdata-rs/tests/features/src/enums/structs.rs index 0fcd8cf8..b78bf944 100644 --- a/flatdata-rs/tests/features/src/enums/structs.rs +++ b/flatdata-rs/tests/features/src/enums/structs.rs @@ -4,35 +4,35 @@ include!(concat!(env!("OUT_DIR"), "/enums/structs.rs")); #[test] fn enums_in_structs() { - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(n::EnumI8::Value); - assert_eq!(buf.get().f(), n::EnumI8::Value); + let mut value = n::StructEnumI8::new(); + value.set_f(n::EnumI8::Value); + assert_eq!(value.f(), n::EnumI8::Value); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(n::EnumU8::Value); - assert_eq!(buf.get().f(), n::EnumU8::Value); + let mut value = n::StructEnumU8::new(); + value.set_f(n::EnumU8::Value); + assert_eq!(value.f(), n::EnumU8::Value); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(n::EnumI16::Value); - assert_eq!(buf.get().f(), n::EnumI16::Value); + let mut value = n::StructEnumI16::new(); + value.set_f(n::EnumI16::Value); + assert_eq!(value.f(), n::EnumI16::Value); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(n::EnumU16::Value); - assert_eq!(buf.get().f(), n::EnumU16::Value); + let mut value = n::StructEnumU16::new(); + value.set_f(n::EnumU16::Value); + assert_eq!(value.f(), n::EnumU16::Value); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(n::EnumI32::Value); - assert_eq!(buf.get().f(), n::EnumI32::Value); + let mut value = n::StructEnumI32::new(); + value.set_f(n::EnumI32::Value); + assert_eq!(value.f(), n::EnumI32::Value); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(n::EnumU32::Value); - assert_eq!(buf.get().f(), n::EnumU32::Value); + let mut value = n::StructEnumU32::new(); + value.set_f(n::EnumU32::Value); + assert_eq!(value.f(), n::EnumU32::Value); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(n::EnumI64::Value); - assert_eq!(buf.get().f(), n::EnumI64::Value); + let mut value = n::StructEnumI64::new(); + value.set_f(n::EnumI64::Value); + assert_eq!(value.f(), n::EnumI64::Value); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(n::EnumU64::Value); - assert_eq!(buf.get().f(), n::EnumU64::Value); + let mut value = n::StructEnumU64::new(); + value.set_f(n::EnumU64::Value); + assert_eq!(value.f(), n::EnumU64::Value); } diff --git a/flatdata-rs/tests/features/src/structs/integers.rs b/flatdata-rs/tests/features/src/structs/integers.rs index 0ccf279c..dfa371c4 100644 --- a/flatdata-rs/tests/features/src/structs/integers.rs +++ b/flatdata-rs/tests/features/src/structs/integers.rs @@ -18,70 +18,70 @@ fn test_sizes() { #[test] fn test_min_values() { - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::u8::MIN); - assert_eq!(buf.get().f(), std::u8::MIN); + let mut value = n::U8::new(); + value.set_f(std::u8::MIN); + assert_eq!(value.f(), std::u8::MIN); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::i8::MIN); - assert_eq!(buf.get().f(), std::i8::MIN); + let mut value = n::I8::new(); + value.set_f(std::i8::MIN); + assert_eq!(value.f(), std::i8::MIN); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::u16::MIN); - assert_eq!(buf.get().f(), std::u16::MIN); + let mut value = n::U16::new(); + value.set_f(std::u16::MIN); + assert_eq!(value.f(), std::u16::MIN); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::i16::MIN); - assert_eq!(buf.get().f(), std::i16::MIN); + let mut value = n::I16::new(); + value.set_f(std::i16::MIN); + assert_eq!(value.f(), std::i16::MIN); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::u32::MIN); - assert_eq!(buf.get().f(), std::u32::MIN); + let mut value = n::U32::new(); + value.set_f(std::u32::MIN); + assert_eq!(value.f(), std::u32::MIN); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::i32::MIN); - assert_eq!(buf.get().f(), std::i32::MIN); + let mut value = n::I32::new(); + value.set_f(std::i32::MIN); + assert_eq!(value.f(), std::i32::MIN); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::u64::MIN); - assert_eq!(buf.get().f(), std::u64::MIN); + let mut value = n::U64::new(); + value.set_f(std::u64::MIN); + assert_eq!(value.f(), std::u64::MIN); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::i64::MIN); - assert_eq!(buf.get().f(), std::i64::MIN); + let mut value = n::I64::new(); + value.set_f(std::i64::MIN); + assert_eq!(value.f(), std::i64::MIN); } #[test] fn test_max_values() { - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::u8::MAX); - assert_eq!(buf.get().f(), std::u8::MAX); + let mut value = n::U8::new(); + value.set_f(std::u8::MAX); + assert_eq!(value.f(), std::u8::MAX); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::i8::MAX); - assert_eq!(buf.get().f(), std::i8::MAX); + let mut value = n::I8::new(); + value.set_f(std::i8::MAX); + assert_eq!(value.f(), std::i8::MAX); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::u16::MAX); - assert_eq!(buf.get().f(), std::u16::MAX); + let mut value = n::U16::new(); + value.set_f(std::u16::MAX); + assert_eq!(value.f(), std::u16::MAX); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::i16::MAX); - assert_eq!(buf.get().f(), std::i16::MAX); + let mut value = n::I16::new(); + value.set_f(std::i16::MAX); + assert_eq!(value.f(), std::i16::MAX); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::u32::MAX); - assert_eq!(buf.get().f(), std::u32::MAX); + let mut value = n::U32::new(); + value.set_f(std::u32::MAX); + assert_eq!(value.f(), std::u32::MAX); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::i32::MAX); - assert_eq!(buf.get().f(), std::i32::MAX); + let mut value = n::I32::new(); + value.set_f(std::i32::MAX); + assert_eq!(value.f(), std::i32::MAX); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::u64::MAX); - assert_eq!(buf.get().f(), std::u64::MAX); + let mut value = n::U64::new(); + value.set_f(std::u64::MAX); + assert_eq!(value.f(), std::u64::MAX); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(std::i64::MAX); - assert_eq!(buf.get().f(), std::i64::MAX); + let mut value = n::I64::new(); + value.set_f(std::i64::MAX); + assert_eq!(value.f(), std::i64::MAX); } diff --git a/flatdata-rs/tests/features/src/structs/unaligned.rs b/flatdata-rs/tests/features/src/structs/unaligned.rs index 83a0ba2e..b95cc4c6 100644 --- a/flatdata-rs/tests/features/src/structs/unaligned.rs +++ b/flatdata-rs/tests/features/src/structs/unaligned.rs @@ -18,70 +18,70 @@ fn test_sizes() { #[test] fn test_min_values() { - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(0); - assert_eq!(buf.get().f(), 0); + let mut value = n::U8::new(); + value.set_f(0); + assert_eq!(value.f(), 0); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(-(1 << (8 - 3 - 1))); - assert_eq!(buf.get().f(), -(1 << (8 - 3 - 1))); + let mut value = n::I8::new(); + value.set_f(-(1 << (8 - 3 - 1))); + assert_eq!(value.f(), -(1 << (8 - 3 - 1))); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(0); - assert_eq!(buf.get().f(), 0); + let mut value = n::U16::new(); + value.set_f(0); + assert_eq!(value.f(), 0); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(-(1 << (16 - 3 - 1))); - assert_eq!(buf.get().f(), -(1 << (16 - 3 - 1))); + let mut value = n::I16::new(); + value.set_f(-(1 << (16 - 3 - 1))); + assert_eq!(value.f(), -(1 << (16 - 3 - 1))); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(0); - assert_eq!(buf.get().f(), 0); + let mut value = n::U32::new(); + value.set_f(0); + assert_eq!(value.f(), 0); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(-(1 << (32 - 3 - 1))); - assert_eq!(buf.get().f(), -(1 << (32 - 3 - 1))); + let mut value = n::I32::new(); + value.set_f(-(1 << (32 - 3 - 1))); + assert_eq!(value.f(), -(1 << (32 - 3 - 1))); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(0); - assert_eq!(buf.get().f(), 0); + let mut value = n::U64::new(); + value.set_f(0); + assert_eq!(value.f(), 0); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f(-(1 << (64 - 3 - 1))); - assert_eq!(buf.get().f(), -(1 << (64 - 3 - 1))); + let mut value = n::I64::new(); + value.set_f(-(1 << (64 - 3 - 1))); + assert_eq!(value.f(), -(1 << (64 - 3 - 1))); } #[test] fn test_max_values() { - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f((1 << (8 - 3)) - 1); - assert_eq!(buf.get().f(), (1 << (8 - 3)) - 1); + let mut value = n::U8::new(); + value.set_f((1 << (8 - 3)) - 1); + assert_eq!(value.f(), (1 << (8 - 3)) - 1); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f((1 << (8 - 3) - 1) - 1); - assert_eq!(buf.get().f(), (1 << (8 - 3 - 1)) - 1); + let mut value = n::I8::new(); + value.set_f((1 << (8 - 3) - 1) - 1); + assert_eq!(value.f(), (1 << (8 - 3 - 1)) - 1); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f((1 << (16 - 3)) - 1); - assert_eq!(buf.get().f(), (1 << (16 - 3)) - 1); + let mut value = n::U16::new(); + value.set_f((1 << (16 - 3)) - 1); + assert_eq!(value.f(), (1 << (16 - 3)) - 1); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f((1 << (16 - 3 - 1)) - 1); - assert_eq!(buf.get().f(), (1 << (16 - 3 - 1)) - 1); + let mut value = n::I16::new(); + value.set_f((1 << (16 - 3 - 1)) - 1); + assert_eq!(value.f(), (1 << (16 - 3 - 1)) - 1); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f((1 << (32 - 3)) - 1); - assert_eq!(buf.get().f(), (1 << (32 - 3)) - 1); + let mut value = n::U32::new(); + value.set_f((1 << (32 - 3)) - 1); + assert_eq!(value.f(), (1 << (32 - 3)) - 1); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f((1 << (32 - 3 - 1)) - 1); - assert_eq!(buf.get().f(), (1 << (32 - 3 - 1)) - 1); + let mut value = n::I32::new(); + value.set_f((1 << (32 - 3 - 1)) - 1); + assert_eq!(value.f(), (1 << (32 - 3 - 1)) - 1); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f((1 << (64 - 3)) - 1); - assert_eq!(buf.get().f(), (1 << (64 - 3)) - 1); + let mut value = n::U64::new(); + value.set_f((1 << (64 - 3)) - 1); + assert_eq!(value.f(), (1 << (64 - 3)) - 1); - let mut buf = flatdata::StructBuf::::new(); - buf.get_mut().set_f((1 << (64 - 3 - 1)) - 1); - assert_eq!(buf.get().f(), (1 << (64 - 3 - 1)) - 1); + let mut value = n::I64::new(); + value.set_f((1 << (64 - 3 - 1)) - 1); + assert_eq!(value.f(), (1 << (64 - 3 - 1)) - 1); }