diff --git a/python/src/streaming_data_types/__init__.py b/python/src/streaming_data_types/__init__.py index 0cbc8fa..a3d3890 100644 --- a/python/src/streaming_data_types/__init__.py +++ b/python/src/streaming_data_types/__init__.py @@ -18,6 +18,7 @@ from streaming_data_types.status_x5f2 import deserialise_x5f2, serialise_x5f2 from streaming_data_types.units_un00 import serialise_un00, deserialise_un00 from streaming_data_types.pulse_metadata_pu00 import serialise_pu00, deserialise_pu00 +from streaming_data_types.vetoes_vc00 import serialise_vc00, deserialise_vc00 __version__ = version @@ -39,6 +40,7 @@ "da00": serialise_da00, "un00": serialise_un00, "pu00": serialise_pu00, + "vc00": serialise_vc00, } @@ -59,4 +61,5 @@ "da00": deserialise_da00, "un00": deserialise_un00, "pu00": deserialise_pu00, + "vc00": deserialise_vc00, } diff --git a/python/src/streaming_data_types/fbschemas/vetoes_vc00/Vetoes.py b/python/src/streaming_data_types/fbschemas/vetoes_vc00/Vetoes.py new file mode 100644 index 0000000..3aaab5e --- /dev/null +++ b/python/src/streaming_data_types/fbschemas/vetoes_vc00/Vetoes.py @@ -0,0 +1,67 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: + +import flatbuffers +from flatbuffers.compat import import_numpy +np = import_numpy() + +class Vetoes(object): + __slots__ = ['_tab'] + + @classmethod + def GetRootAs(cls, buf, offset=0): + n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset) + x = Vetoes() + x.Init(buf, n + offset) + return x + + @classmethod + def GetRootAsVetoes(cls, buf, offset=0): + """This method is deprecated. Please switch to GetRootAs.""" + return cls.GetRootAs(buf, offset) + @classmethod + def VetoesBufferHasIdentifier(cls, buf, offset, size_prefixed=False): + return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x76\x63\x30\x30", size_prefixed=size_prefixed) + + # Vetoes + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # Vetoes + def Timestamp(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos) + return 0 + + # Vetoes + def Vetoes(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos) + return 0 + +def VetoesStart(builder): + builder.StartObject(2) + +def Start(builder): + VetoesStart(builder) + +def VetoesAddTimestamp(builder, timestamp): + builder.PrependInt64Slot(0, timestamp, 0) + +def AddTimestamp(builder, timestamp): + VetoesAddTimestamp(builder, timestamp) + +def VetoesAddVetoes(builder, vetoes): + builder.PrependUint32Slot(1, vetoes, 0) + +def AddVetoes(builder, vetoes): + VetoesAddVetoes(builder, vetoes) + +def VetoesEnd(builder): + return builder.EndObject() + +def End(builder): + return VetoesEnd(builder) diff --git a/python/src/streaming_data_types/fbschemas/vetoes_vc00/__init__.py b/python/src/streaming_data_types/fbschemas/vetoes_vc00/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/src/streaming_data_types/vetoes_vc00.py b/python/src/streaming_data_types/vetoes_vc00.py new file mode 100644 index 0000000..7822ed9 --- /dev/null +++ b/python/src/streaming_data_types/vetoes_vc00.py @@ -0,0 +1,28 @@ +from collections import namedtuple + +import flatbuffers + +from streaming_data_types.fbschemas.vetoes_vc00 import Vetoes +from streaming_data_types.utils import check_schema_identifier + +FILE_IDENTIFIER = b"vc00" + +VetoesInfo = namedtuple("VetoesInfo", ("timestamp_ns", "vetoes")) + + +def deserialise_vc00(buffer) -> VetoesInfo: + check_schema_identifier(buffer, FILE_IDENTIFIER) + vetoes = Vetoes.Vetoes.GetRootAsVetoes(buffer, 0) + return VetoesInfo( + vetoes.Timestamp(), + vetoes.Vetoes(), + ) + + +def serialise_vc00(timestamp_ns: int, vetoes: int) -> bytes: + builder = flatbuffers.Builder(128) + Vetoes.Start(builder) + Vetoes.AddTimestamp(builder, timestamp_ns) + Vetoes.AddVetoes(builder, vetoes) + builder.Finish(Vetoes.VetoesEnd(builder), file_identifier=FILE_IDENTIFIER) + return bytes(builder.Output()) diff --git a/python/tests/test_vc00.py b/python/tests/test_vc00.py new file mode 100644 index 0000000..521d4b1 --- /dev/null +++ b/python/tests/test_vc00.py @@ -0,0 +1,31 @@ +import pytest + +from streaming_data_types import DESERIALISERS, SERIALISERS +from streaming_data_types.exceptions import WrongSchemaException +from streaming_data_types.vetoes_vc00 import deserialise_vc00, serialise_vc00 + + +class TestSerialisationUn00: + def test_serialises_and_deserialises_vc00_message_correctly(self): + """ + Round-trip to check what we serialise is what we get back. + """ + buf = serialise_vc00(1234567890, 0x1) + entry = deserialise_vc00(buf) + + assert entry.timestamp_ns == 1234567890 + assert entry.vetoes == 0x1 + + def test_if_buffer_has_wrong_id_then_throws(self): + buf = serialise_vc00(1234567890, 0x1) + + # Manually hack the id + buf = bytearray(buf) + buf[4:8] = b"1234" + + with pytest.raises(WrongSchemaException): + deserialise_vc00(buf) + + def test_schema_type_is_in_global_serialisers_list(self): + assert "vc00" in SERIALISERS + assert "vc00" in DESERIALISERS diff --git a/rust/src/flatbuffers_generated/mod.rs b/rust/src/flatbuffers_generated/mod.rs index 9aedece..11a8ad4 100644 --- a/rust/src/flatbuffers_generated/mod.rs +++ b/rust/src/flatbuffers_generated/mod.rs @@ -1,36 +1,38 @@ -#[path = "6s4t_run_stop.rs"] -pub mod run_stop_6s4t; -#[path = "ad00_area_detector_array.rs"] -pub mod area_detector_array_ad00; -#[path = "al00_alarm.rs"] -pub mod alarm_al00; -#[path = "answ_action_response.rs"] -pub mod action_response_answ; -#[path = "da00_dataarray.rs"] -pub mod dataarray_da00; +#[path = "pu00_pulse_metadata.rs"] +pub mod pulse_metadata_pu00; +#[path = "fc00_forwarder_config.rs"] +pub mod forwarder_config_fc00; +#[path = "vc00_veto_configuration.rs"] +pub mod veto_configuration_vc00; #[path = "df12_det_spec_map.rs"] pub mod det_spec_map_df12; -#[path = "ep01_epics_connection.rs"] -pub mod epics_connection_ep01; #[path = "ev44_events.rs"] pub mod events_ev44; -#[path = "f144_logdata.rs"] -pub mod logdata_f144; -#[path = "fc00_forwarder_config.rs"] -pub mod forwarder_config_fc00; -#[path = "hs01_event_histogram.rs"] -pub mod event_histogram_hs01; +#[path = "ad00_area_detector_array.rs"] +pub mod area_detector_array_ad00; +#[path = "un00_units.rs"] +pub mod units_un00; +#[path = "se00_data.rs"] +pub mod data_se00; +#[path = "ep01_epics_connection.rs"] +pub mod epics_connection_ep01; +#[path = "6s4t_run_stop.rs"] +pub mod run_stop_6s4t; #[path = "json_json.rs"] pub mod json_json; #[path = "pl72_run_start.rs"] pub mod run_start_pl72; -#[path = "pu00_pulse_metadata.rs"] -pub mod pulse_metadata_pu00; -#[path = "se00_data.rs"] -pub mod data_se00; -#[path = "un00_units.rs"] -pub mod units_un00; -#[path = "wrdn_finished_writing.rs"] -pub mod finished_writing_wrdn; +#[path = "answ_action_response.rs"] +pub mod action_response_answ; #[path = "x5f2_status.rs"] pub mod status_x5f2; +#[path = "da00_dataarray.rs"] +pub mod dataarray_da00; +#[path = "hs01_event_histogram.rs"] +pub mod event_histogram_hs01; +#[path = "f144_logdata.rs"] +pub mod logdata_f144; +#[path = "wrdn_finished_writing.rs"] +pub mod finished_writing_wrdn; +#[path = "al00_alarm.rs"] +pub mod alarm_al00; diff --git a/rust/src/flatbuffers_generated/vc00_veto_configuration.rs b/rust/src/flatbuffers_generated/vc00_veto_configuration.rs new file mode 100644 index 0000000..5081630 --- /dev/null +++ b/rust/src/flatbuffers_generated/vc00_veto_configuration.rs @@ -0,0 +1,208 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +// @generated + +use core::mem; +use core::cmp::Ordering; + +extern crate flatbuffers; +use self::flatbuffers::{EndianScalar, Follow}; + +pub enum VetoesOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Vetoes<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Vetoes<'a> { + type Inner = Vetoes<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> Vetoes<'a> { + pub const VT_TIMESTAMP: flatbuffers::VOffsetT = 4; + pub const VT_VETOES: flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Vetoes { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args VetoesArgs + ) -> flatbuffers::WIPOffset> { + let mut builder = VetoesBuilder::new(_fbb); + builder.add_timestamp(args.timestamp); + builder.add_vetoes(args.vetoes); + builder.finish() + } + + + #[inline] + pub fn timestamp(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Vetoes::VT_TIMESTAMP, Some(0)).unwrap()} + } + #[inline] + pub fn vetoes(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Vetoes::VT_VETOES, Some(0)).unwrap()} + } +} + +impl flatbuffers::Verifiable for Vetoes<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::("timestamp", Self::VT_TIMESTAMP, false)? + .visit_field::("vetoes", Self::VT_VETOES, false)? + .finish(); + Ok(()) + } +} +pub struct VetoesArgs { + pub timestamp: i64, + pub vetoes: u32, +} +impl<'a> Default for VetoesArgs { + #[inline] + fn default() -> Self { + VetoesArgs { + timestamp: 0, + vetoes: 0, + } + } +} + +pub struct VetoesBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> VetoesBuilder<'a, 'b, A> { + #[inline] + pub fn add_timestamp(&mut self, timestamp: i64) { + self.fbb_.push_slot::(Vetoes::VT_TIMESTAMP, timestamp, 0); + } + #[inline] + pub fn add_vetoes(&mut self, vetoes: u32) { + self.fbb_.push_slot::(Vetoes::VT_VETOES, vetoes, 0); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> VetoesBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + VetoesBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Vetoes<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Vetoes"); + ds.field("timestamp", &self.timestamp()); + ds.field("vetoes", &self.vetoes()); + ds.finish() + } +} +#[inline] +/// Verifies that a buffer of bytes contains a `Vetoes` +/// and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_vetoes_unchecked`. +pub fn root_as_vetoes(buf: &[u8]) -> Result { + flatbuffers::root::(buf) +} +#[inline] +/// Verifies that a buffer of bytes contains a size prefixed +/// `Vetoes` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `size_prefixed_root_as_vetoes_unchecked`. +pub fn size_prefixed_root_as_vetoes(buf: &[u8]) -> Result { + flatbuffers::size_prefixed_root::(buf) +} +#[inline] +/// Verifies, with the given options, that a buffer of bytes +/// contains a `Vetoes` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_vetoes_unchecked`. +pub fn root_as_vetoes_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::root_with_opts::>(opts, buf) +} +#[inline] +/// Verifies, with the given verifier options, that a buffer of +/// bytes contains a size prefixed `Vetoes` and returns +/// it. Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_vetoes_unchecked`. +pub fn size_prefixed_root_as_vetoes_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::size_prefixed_root_with_opts::>(opts, buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a Vetoes and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid `Vetoes`. +pub unsafe fn root_as_vetoes_unchecked(buf: &[u8]) -> Vetoes { + unsafe { flatbuffers::root_unchecked::(buf) } +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a size prefixed Vetoes and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid size prefixed `Vetoes`. +pub unsafe fn size_prefixed_root_as_vetoes_unchecked(buf: &[u8]) -> Vetoes { + unsafe { flatbuffers::size_prefixed_root_unchecked::(buf) } +} +pub const VETOES_IDENTIFIER: &str = "vc00"; + +#[inline] +pub fn vetoes_buffer_has_identifier(buf: &[u8]) -> bool { + flatbuffers::buffer_has_identifier(buf, VETOES_IDENTIFIER, false) +} + +#[inline] +pub fn vetoes_size_prefixed_buffer_has_identifier(buf: &[u8]) -> bool { + flatbuffers::buffer_has_identifier(buf, VETOES_IDENTIFIER, true) +} + +#[inline] +pub fn finish_vetoes_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( + fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + root: flatbuffers::WIPOffset>) { + fbb.finish(root, Some(VETOES_IDENTIFIER)); +} + +#[inline] +pub fn finish_size_prefixed_vetoes_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>(fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, root: flatbuffers::WIPOffset>) { + fbb.finish_size_prefixed(root, Some(VETOES_IDENTIFIER)); +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 35a1a7a..a90f973 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -26,11 +26,12 @@ use crate::flatbuffers_generated::run_start_pl72::{RunStart, root_as_run_start}; use crate::flatbuffers_generated::run_stop_6s4t::{RunStop, root_as_run_stop}; use crate::flatbuffers_generated::status_x5f2::{Status, root_as_status}; use crate::flatbuffers_generated::units_un00::{Units, root_as_units}; +use crate::flatbuffers_generated::veto_configuration_vc00::{Vetoes, root_as_vetoes}; use flatbuffers::InvalidFlatbuffer; #[allow(clippy::all)] #[rustfmt::skip] -#[allow(dead_code, unused, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[allow(dead_code, unused, non_snake_case, non_camel_case_types, non_upper_case_globals, mismatched_lifetime_syntaxes)] pub mod flatbuffers_generated; /// Enum containing all possible messages currently supported by @@ -55,6 +56,7 @@ pub enum DeserializedMessage<'a> { AlarmAl00(Alarm<'a>), DataArrayDa00(da00_DataArray<'a>), UnitsUn00(Units<'a>), + VetoesVc00(Vetoes<'a>), } /// Error raised from `deserialize_message` describing why a message @@ -124,6 +126,7 @@ pub fn deserialize_message(data: &[u8]) -> Result, Deser root_as_da_00_data_array(data)?, )), Some(b"un00") => Ok(DeserializedMessage::UnitsUn00(root_as_units(data)?)), + Some(b"vc00") => Ok(DeserializedMessage::VetoesVc00(root_as_vetoes(data)?)), _ => Err(DeserializationError::UnsupportedSchema( "Unknown message type passed to deserialize".to_owned(), )), diff --git a/schemas/vc00_veto_configuration.fbs b/schemas/vc00_veto_configuration.fbs new file mode 100644 index 0000000..052ecbf --- /dev/null +++ b/schemas/vc00_veto_configuration.fbs @@ -0,0 +1,12 @@ +// Schema for showing the current veto configuration. +// This contains essentially a bitwise OR of soft and hard vetoes. + +file_identifier "vc00"; + +table Vetoes { + timestamp: long; // Nanoseconds since UNIX epoch + vetoes: uint; // A bit mask of the configured vetoes. For the individual bits see + // https://isiscomputinggroup.github.io/ibex_developers_manual/specific_iocs/datastreaming/Datastreaming-vetos +} + +root_type Vetoes;