diff --git a/src/network_management/network_manager.rs b/src/network_management/network_manager.rs index 7314bd1..764e08d 100644 --- a/src/network_management/network_manager.rs +++ b/src/network_management/network_manager.rs @@ -158,7 +158,7 @@ impl NetworkManager { self.get_control_function_address_by_name(destination.get_name()), priority, ) - .unwrap_or(CanId::default()); + .unwrap_or_default(); if message_id.raw() != CanId::default().raw() { self.enqueue_can_message( diff --git a/src/object_pool/mod.rs b/src/object_pool/mod.rs index c12c414..5b0a3b0 100644 --- a/src/object_pool/mod.rs +++ b/src/object_pool/mod.rs @@ -2,7 +2,7 @@ pub mod colour; pub mod reader; pub mod writer; -mod object; +pub mod object; mod object_attributes; mod object_id; mod object_pool; @@ -12,6 +12,9 @@ mod vt_version; use crate::network_management::name::NAME; pub use colour::Colour; +pub use object_attributes::ObjectRef; +pub use object_id::NullableObjectId; +pub use object_id::ObjectId; pub use object_pool::ObjectPool; pub use object_type::ObjectType; @@ -19,4 +22,7 @@ pub use object_type::ObjectType; pub enum ParseError { DataEmpty, UnknownObjectType, + UnexpectedNullObjectId, + BooleanOutOfRange, + UnsupportedVtVersion, } diff --git a/src/object_pool/object.rs b/src/object_pool/object.rs index 39bdb66..eb4acb0 100644 --- a/src/object_pool/object.rs +++ b/src/object_pool/object.rs @@ -11,6 +11,8 @@ use crate::object_pool::object_attributes::{ use crate::object_pool::object_id::ObjectId; use crate::object_pool::{Colour, ObjectType}; +use super::object_id::NullableObjectId; + #[derive(Debug)] pub enum Object { WorkingSet(WorkingSet), @@ -26,6 +28,7 @@ pub enum Object { InputList(InputList), OutputString(OutputString), OutputNumber(OutputNumber), + OutputList(OutputList), OutputLine(OutputLine), OutputRectangle(OutputRectangle), OutputEllipse(OutputEllipse), @@ -50,7 +53,6 @@ pub enum Object { WindowMask(WindowMask), KeyGroup(KeyGroup), GraphicsContext(GraphicsContext), - OutputList(OutputList), ExtendedInputAttributes(ExtendedInputAttributes), ColourMap(ColourMap), ObjectLabelReferenceList(ObjectLabelReferenceList), @@ -80,6 +82,7 @@ impl Object { Object::InputList(o) => o.id, Object::OutputString(o) => o.id, Object::OutputNumber(o) => o.id, + Object::OutputList(o) => o.id, Object::OutputLine(o) => o.id, Object::OutputRectangle(o) => o.id, Object::OutputEllipse(o) => o.id, @@ -104,7 +107,6 @@ impl Object { Object::WindowMask(o) => o.id, Object::KeyGroup(o) => o.id, Object::GraphicsContext(o) => o.id, - Object::OutputList(o) => o.id, Object::ExtendedInputAttributes(o) => o.id, Object::ColourMap(o) => o.id, Object::ObjectLabelReferenceList(o) => o.id, @@ -134,6 +136,7 @@ impl Object { Object::InputList(_) => ObjectType::InputList, Object::OutputString(_) => ObjectType::OutputString, Object::OutputNumber(_) => ObjectType::OutputNumber, + Object::OutputList(_) => ObjectType::OutputList, Object::OutputLine(_) => ObjectType::OutputLine, Object::OutputRectangle(_) => ObjectType::OutputRectangle, Object::OutputEllipse(_) => ObjectType::OutputEllipse, @@ -160,7 +163,6 @@ impl Object { Object::WindowMask(_) => ObjectType::WindowMask, Object::KeyGroup(_) => ObjectType::KeyGroup, Object::GraphicsContext(_) => ObjectType::GraphicsContext, - Object::OutputList(_) => ObjectType::OutputList, Object::ExtendedInputAttributes(_) => ObjectType::ExtendedInputAttributes, Object::ColourMap(_) => ObjectType::ColourMap, Object::ObjectLabelReferenceList(_) => ObjectType::ObjectLabelReferenceList, @@ -174,6 +176,171 @@ impl Object { Object::ScaledGraphic(_) => ObjectType::ScaledGraphic, } } + + /// + /// Returns a list of object IDs referenced by this object in the order they are listed + /// as attributes in the object specification. + /// + /// # Examples + /// We can use this method recursively to process objects in a "depth-first" manner + /// as required by the ISO 11783-6 (ch. 4.6.1.3) standard: + /// ``` + /// use ag_iso_stack::object_pool::ObjectId; + /// use ag_iso_stack::object_pool::ObjectPool; + /// + /// fn process_object(object_pool: &ObjectPool, object_id: ObjectId) { + /// let object = object_pool.object_by_id(object_id).unwrap(); + /// for referenced_object_id in object.referenced_objects() { + /// process_object(object_pool, referenced_object_id); + /// } + /// // Process the object here + /// } + /// + /// let working_set = object_pool.working_set_object().unwrap(); + /// process_object(&object_pool, working_set.id); + /// + pub fn referenced_objects(&self) -> Vec { + let mut refs: Vec = vec![]; + + fn extend_object_refs(refs: &mut Vec, object_refs: &[ObjectRef]) { + refs.extend(object_refs.iter().map(|x| x.id)); + } + + fn push_nullable_id(refs: &mut Vec, nullable_id: &NullableObjectId) { + if let Some(id) = nullable_id.0 { + refs.push(id); + } + } + + fn extend_nullable_ids(refs: &mut Vec, nullable_ids: &[NullableObjectId]) { + refs.extend(nullable_ids.iter().filter_map(|x| x.0)); + } + + match self { + Object::WorkingSet(o) => { + refs.push(o.active_mask); + extend_object_refs(&mut refs, &o.object_refs); + } + Object::DataMask(o) => { + push_nullable_id(&mut refs, &o.soft_key_mask); + extend_object_refs(&mut refs, &o.object_refs); + } + Object::AlarmMask(o) => { + push_nullable_id(&mut refs, &o.soft_key_mask); + extend_object_refs(&mut refs, &o.object_refs); + } + Object::Container(o) => extend_object_refs(&mut refs, &o.object_refs), + Object::SoftKeyMask(o) => refs.extend(&o.objects), + Object::Key(o) => extend_object_refs(&mut refs, &o.object_refs), + Object::Button(o) => extend_object_refs(&mut refs, &o.object_refs), + Object::InputBoolean(o) => { + refs.push(o.foreground_colour); + push_nullable_id(&mut refs, &o.variable_reference); + } + Object::InputString(o) => { + refs.push(o.font_attributes); + push_nullable_id(&mut refs, &o.input_attributes); + push_nullable_id(&mut refs, &o.variable_reference); + } + Object::InputNumber(o) => { + refs.push(o.font_attributes); + push_nullable_id(&mut refs, &o.variable_reference); + } + Object::InputList(o) => { + push_nullable_id(&mut refs, &o.variable_reference); + extend_nullable_ids(&mut refs, &o.list_items); + } + Object::OutputString(o) => { + refs.push(o.font_attributes); + push_nullable_id(&mut refs, &o.variable_reference); + } + Object::OutputNumber(o) => { + refs.push(o.font_attributes); + push_nullable_id(&mut refs, &o.variable_reference); + } + Object::OutputList(o) => { + push_nullable_id(&mut refs, &o.variable_reference); + extend_nullable_ids(&mut refs, &o.list_items); + } + Object::OutputLine(o) => refs.push(o.line_attributes), + Object::OutputRectangle(o) => { + refs.push(o.line_attributes); + push_nullable_id(&mut refs, &o.fill_attributes); + } + Object::OutputEllipse(o) => { + refs.push(o.line_attributes); + push_nullable_id(&mut refs, &o.fill_attributes); + } + Object::OutputPolygon(o) => { + refs.push(o.line_attributes); + push_nullable_id(&mut refs, &o.fill_attributes); + } + Object::OutputMeter(o) => push_nullable_id(&mut refs, &o.variable_reference), + Object::OutputLinearBarGraph(o) => { + push_nullable_id(&mut refs, &o.variable_reference); + push_nullable_id(&mut refs, &o.target_value_variable_reference); + } + Object::OutputArchedBarGraph(o) => { + push_nullable_id(&mut refs, &o.variable_reference); + push_nullable_id(&mut refs, &o.target_value_variable_reference); + } + Object::PictureGraphic(_) + | Object::NumberVariable(_) + | Object::StringVariable(_) + | Object::FontAttributes(_) + | Object::LineAttributes(_) => (), // No references + Object::FillAttributes(o) => push_nullable_id(&mut refs, &o.fill_pattern), + Object::InputAttributes(_) => (), // No references + Object::ObjectPointer(o) => push_nullable_id(&mut refs, &o.value), + Object::Macro(_) + | Object::AuxiliaryFunctionType1(_) + | Object::AuxiliaryInputType1(_) + | Object::AuxiliaryFunctionType2(_) + | Object::AuxiliaryInputType2(_) => (), // No references + Object::AuxiliaryControlDesignatorType2(o) => refs.push(o.auxiliary_object_id), + Object::WindowMask(o) => { + push_nullable_id(&mut refs, &o.window_title); + push_nullable_id(&mut refs, &o.window_icon); + extend_nullable_ids(&mut refs, &o.objects); + extend_object_refs(&mut refs, &o.object_refs); + } + Object::KeyGroup(o) => { + refs.push(o.name); + push_nullable_id(&mut refs, &o.key_group_icon); + refs.extend(&o.objects); + } + Object::GraphicsContext(o) => { + push_nullable_id(&mut refs, &o.font_attributes_object); + push_nullable_id(&mut refs, &o.line_attributes_object); + push_nullable_id(&mut refs, &o.fill_attributes_object); + } + Object::ExtendedInputAttributes(_) | Object::ColourMap(_) => (), // No references + Object::ObjectLabelReferenceList(o) => { + for label in o.object_labels.as_slice() { + refs.push(label.id); + push_nullable_id(&mut refs, &label.string_variable_reference); + push_nullable_id(&mut refs, &label.graphic_representation); + } + } + Object::ExternalObjectDefinition(o) => extend_nullable_ids(&mut refs, &o.objects), + Object::ExternalReferenceName(_) => (), // No references + Object::ExternalObjectPointer(o) => { + push_nullable_id(&mut refs, &o.default_object_id); + push_nullable_id(&mut refs, &o.external_reference_name_id); + push_nullable_id(&mut refs, &o.external_object_id); + } + Object::Animation(o) => extend_object_refs(&mut refs, &o.object_refs), + + Object::ColourPalette(_) | Object::GraphicData(_) => (), // No references + Object::WorkingSetSpecialControls(o) => { + push_nullable_id(&mut refs, &o.id_of_colour_map); + push_nullable_id(&mut refs, &o.id_of_colour_palette); + } + Object::ScaledGraphic(o) => push_nullable_id(&mut refs, &o.value), + }; + + refs + } } #[derive(Debug, PartialEq)] @@ -191,7 +358,7 @@ pub struct WorkingSet { pub struct DataMask { pub id: ObjectId, pub background_colour: u8, - pub soft_key_mask: ObjectId, + pub soft_key_mask: NullableObjectId, pub object_refs: Vec, pub macro_refs: Vec, } @@ -200,7 +367,7 @@ pub struct DataMask { pub struct AlarmMask { pub id: ObjectId, pub background_colour: u8, - pub soft_key_mask: ObjectId, + pub soft_key_mask: NullableObjectId, pub priority: u8, pub acoustic_signal: u8, pub object_refs: Vec, @@ -253,7 +420,7 @@ pub struct InputBoolean { pub background_colour: u8, pub width: u16, pub foreground_colour: ObjectId, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub value: bool, pub enabled: bool, pub macro_refs: Vec, @@ -266,9 +433,9 @@ pub struct InputString { pub height: u16, pub background_colour: u8, pub font_attributes: ObjectId, - pub input_attributes: ObjectId, + pub input_attributes: NullableObjectId, pub options: InputStringOptions, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub justification: Alignment, pub value: String, pub enabled: bool, @@ -283,7 +450,7 @@ pub struct InputNumber { pub background_colour: u8, pub font_attributes: ObjectId, pub options: NumberOptions, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub value: u32, pub min_value: u32, pub max_value: u32, @@ -301,10 +468,10 @@ pub struct InputList { pub id: ObjectId, pub width: u16, pub height: u16, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub value: u8, pub options: InputListOptions, - pub list_items: Vec, + pub list_items: Vec, pub macro_refs: Vec, } @@ -316,7 +483,7 @@ pub struct OutputString { pub background_colour: u8, pub font_attributes: ObjectId, pub options: OutputStringOptions, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub justification: Alignment, pub value: String, pub macro_refs: Vec, @@ -330,7 +497,7 @@ pub struct OutputNumber { pub background_colour: u8, pub font_attributes: ObjectId, pub options: NumberOptions, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub value: u32, pub offset: i32, pub scale: f32, @@ -345,9 +512,9 @@ pub struct OutputList { pub id: ObjectId, pub width: u16, pub height: u16, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub value: u8, - pub list_items: Vec, + pub list_items: Vec, pub macro_refs: Vec, } @@ -368,7 +535,7 @@ pub struct OutputRectangle { pub width: u16, pub height: u16, pub line_suppression: u8, - pub fill_attributes: ObjectId, + pub fill_attributes: NullableObjectId, pub macro_refs: Vec, } @@ -381,7 +548,7 @@ pub struct OutputEllipse { pub ellipse_type: u8, pub start_angle: u8, pub end_angle: u8, - pub fill_attributes: ObjectId, + pub fill_attributes: NullableObjectId, pub macro_refs: Vec, } @@ -391,7 +558,7 @@ pub struct OutputPolygon { pub width: u16, pub height: u16, pub line_attributes: ObjectId, - pub fill_attributes: ObjectId, + pub fill_attributes: NullableObjectId, pub polygon_type: u8, pub points: Vec>, pub macro_refs: Vec, @@ -410,7 +577,7 @@ pub struct OutputMeter { pub end_angle: u8, pub min_value: u16, pub max_value: u16, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub value: u16, pub macro_refs: Vec, } @@ -426,9 +593,9 @@ pub struct OutputLinearBarGraph { pub nr_of_ticks: u8, pub min_value: u16, pub max_value: u16, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub value: u16, - pub target_value_variable_reference: ObjectId, + pub target_value_variable_reference: NullableObjectId, pub target_value: u16, pub macro_refs: Vec, } @@ -446,9 +613,9 @@ pub struct OutputArchedBarGraph { pub bar_graph_width: u16, pub min_value: u16, pub max_value: u16, - pub variable_reference: ObjectId, + pub variable_reference: NullableObjectId, pub value: u16, - pub target_value_variable_reference: ObjectId, + pub target_value_variable_reference: NullableObjectId, pub target_value: u16, pub macro_refs: Vec, } @@ -502,7 +669,7 @@ pub struct FillAttributes { pub id: ObjectId, pub fill_type: u8, pub fill_colour: u8, - pub fill_pattern: ObjectId, + pub fill_pattern: NullableObjectId, pub macro_refs: Vec, } @@ -561,7 +728,7 @@ pub struct ExtendedInputAttributes { #[derive(Debug)] pub struct ObjectPointer { pub id: ObjectId, - pub value: ObjectId, + pub value: NullableObjectId, } #[derive(Debug)] @@ -630,9 +797,9 @@ pub struct GraphicsContext { pub graphics_cursor_y: i16, pub foreground_colour: u8, pub background_colour: u8, - pub font_attributes_object: ObjectId, - pub line_attributes_object: ObjectId, - pub fill_attributes_object: ObjectId, + pub font_attributes_object: NullableObjectId, + pub line_attributes_object: NullableObjectId, + pub fill_attributes_object: NullableObjectId, pub format: ColorFormat, pub options: GraphicsContextOptions, pub transparency_colour: u8, @@ -646,9 +813,9 @@ pub struct WindowMask { pub background_colour: u8, pub options: WindowMaskOptions, pub name: ObjectId, - pub window_title: ObjectId, - pub window_icon: ObjectId, - pub objects: Vec, + pub window_title: NullableObjectId, + pub window_icon: NullableObjectId, + pub objects: Vec, pub object_refs: Vec, pub macro_refs: Vec, } @@ -658,7 +825,7 @@ pub struct KeyGroup { pub id: ObjectId, pub options: KeyGroupOptions, pub name: ObjectId, - pub key_group_icon: ObjectId, + pub key_group_icon: NullableObjectId, pub objects: Vec, pub macro_refs: Vec, } @@ -674,7 +841,7 @@ pub struct ExternalObjectDefinition { pub id: ObjectId, pub options: ExternalObjectDefinitionOptions, pub name: NAME, - pub objects: Vec, + pub objects: Vec, } #[derive(Debug)] @@ -687,9 +854,9 @@ pub struct ExternalReferenceName { #[derive(Debug)] pub struct ExternalObjectPointer { pub id: ObjectId, - pub default_object_id: ObjectId, - pub external_reference_name_id: ObjectId, - pub external_object_id: ObjectId, + pub default_object_id: NullableObjectId, + pub external_reference_name_id: NullableObjectId, + pub external_object_id: NullableObjectId, } #[derive(Debug)] @@ -729,14 +896,14 @@ pub struct ScaledGraphic { pub height: u16, pub scale_type: u8, pub options: ScaledGraphicOptions, - pub value: u16, + pub value: NullableObjectId, pub macro_refs: Vec, } #[derive(Debug)] pub struct WorkingSetSpecialControls { pub id: ObjectId, - pub id_of_colour_map: ObjectId, - pub id_of_colour_palette: ObjectId, + pub id_of_colour_map: NullableObjectId, + pub id_of_colour_palette: NullableObjectId, pub language_pairs: Vec<(String, String)>, } diff --git a/src/object_pool/object_attributes.rs b/src/object_pool/object_attributes.rs index 3be6550..ce42ed0 100644 --- a/src/object_pool/object_attributes.rs +++ b/src/object_pool/object_attributes.rs @@ -5,6 +5,8 @@ use bitvec::vec::BitVec; use bitvec::view::BitView; use strum_macros::FromRepr; +use super::object_id::NullableObjectId; + #[derive(FromRepr, Debug, PartialEq, Clone, Copy)] #[repr(u8)] pub enum WindowType { @@ -168,9 +170,9 @@ impl core::ops::Add> for Point { #[derive(Debug)] pub struct ObjectLabel { pub id: ObjectId, - pub string_variable_reference: ObjectId, + pub string_variable_reference: NullableObjectId, pub font_type: u8, - pub graphic_representation: ObjectId, + pub graphic_representation: NullableObjectId, } #[derive(Debug, PartialEq, Clone, Copy)] diff --git a/src/object_pool/object_id.rs b/src/object_pool/object_id.rs index 747649e..fd42461 100644 --- a/src/object_pool/object_id.rs +++ b/src/object_pool/object_id.rs @@ -10,14 +10,15 @@ impl ObjectId { pub fn new(id: u16) -> Result { if id == Self::NULL.id { - Err(ParseError::UnknownObjectType) + Err(ParseError::UnexpectedNullObjectId) } else { Ok(ObjectId { id }) } } } -pub struct NullableObjectId(Option); +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct NullableObjectId(pub Option); impl NullableObjectId { pub const NULL: NullableObjectId = NullableObjectId(None); @@ -74,6 +75,12 @@ impl TryFrom for ObjectId { } } +impl From for Option { + fn from(id: NullableObjectId) -> Self { + return id.0; + } +} + impl From for u16 { fn from(val: ObjectId) -> Self { val.id diff --git a/src/object_pool/object_pool.rs b/src/object_pool/object_pool.rs index 1f6bee7..59edab3 100644 --- a/src/object_pool/object_pool.rs +++ b/src/object_pool/object_pool.rs @@ -79,15 +79,23 @@ impl ObjectPool { where I: IntoIterator, { - let mut data = data.into_iter(); - let mut op = Self::new(); + op.extend_with_iop(data); + op + } + + pub fn extend_with_iop(&mut self, data: I) + where + I: IntoIterator, + { + let mut data = data.into_iter(); while let Ok(o) = Object::read(&mut data) { - op.objects.push(o); + // By the standard, if there already is an object with the same ID, the new object + // replaces the old one + self.objects.retain(|x| x.id() != o.id()); + self.objects.push(o); } - - op } pub fn as_iop(&self) -> Vec { diff --git a/src/object_pool/reader.rs b/src/object_pool/reader.rs index ec56f50..df58023 100644 --- a/src/object_pool/reader.rs +++ b/src/object_pool/reader.rs @@ -1,3 +1,4 @@ +use super::object_id::NullableObjectId; use super::*; use crate::object_pool::colour::Colour; use crate::object_pool::object::*; @@ -70,7 +71,7 @@ impl Object { /* READ COMMON TYPES */ - fn read_objects( + fn read_object_ids( data: &mut dyn Iterator, nr_of_objects: usize, ) -> Result, ParseError> { @@ -81,6 +82,17 @@ impl Object { Ok(objs) } + fn read_nullable_object_ids( + data: &mut dyn Iterator, + nr_of_objects: usize, + ) -> Result, ParseError> { + let mut objs = Vec::new(); + for _ in 0..nr_of_objects { + objs.push(Self::read_u16(data)?.into()); + } + Ok(objs) + } + fn read_object_refs( data: &mut dyn Iterator, nr_of_objects: usize, @@ -156,9 +168,9 @@ impl Object { for _ in 0..nr_of_objects { objs.push(ObjectLabel { id: Self::read_u16(data)?.try_into()?, - string_variable_reference: Self::read_u16(data)?.try_into()?, + string_variable_reference: Self::read_u16(data)?.into(), font_type: Self::read_u8(data)?, - graphic_representation: Self::read_u16(data)?.try_into()?, + graphic_representation: Self::read_u16(data)?.into(), }) } Ok(objs) @@ -215,7 +227,7 @@ impl Object { if d == 0 || d == 1 { Ok(d == 1) } else { - Err(ParseError::UnknownObjectType) + Err(ParseError::BooleanOutOfRange) } } None => Err(ParseError::DataEmpty), @@ -300,6 +312,7 @@ impl Object { } fn read_string(len: usize, data: &mut dyn Iterator) -> Result { let mut s = String::new(); + for _ in 0..len { if let Some(c) = data.next() { s.push(c as char); @@ -363,7 +376,7 @@ impl Object { let mut o = DataMask { id, background_colour: Self::read_u8(data)?, - soft_key_mask: Self::read_u16(data)?.try_into()?, + soft_key_mask: Self::read_u16(data)?.into(), object_refs: Vec::with_capacity(Self::read_u8(data)?.into()), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -383,7 +396,7 @@ impl Object { let mut o = AlarmMask { id, background_colour: Self::read_u8(data)?, - soft_key_mask: Self::read_u16(data)?.try_into()?, + soft_key_mask: Self::read_u16(data)?.into(), priority: Self::read_u8(data)?, acoustic_signal: Self::read_u8(data)?, object_refs: Vec::with_capacity(Self::read_u8(data)?.into()), @@ -431,7 +444,7 @@ impl Object { }; o.objects - .extend(Self::read_objects(data, o.objects.capacity())?); + .extend(Self::read_object_ids(data, o.objects.capacity())?); o.macro_refs .extend(Self::read_macro_refs(data, o.macro_refs.capacity())?); @@ -485,7 +498,7 @@ impl Object { background_colour: Self::read_u8(data)?, width: Self::read_u16(data)?, foreground_colour: Self::read_u16(data)?.try_into()?, - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), value: Self::read_bool(data)?, enabled: Self::read_bool(data)?, macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), @@ -507,9 +520,9 @@ impl Object { height: Self::read_u16(data)?, background_colour: Self::read_u8(data)?, font_attributes: Self::read_u16(data)?.try_into()?, - input_attributes: Self::read_u16(data)?.try_into()?, + input_attributes: Self::read_u16(data)?.into(), options: Self::read_u8(data)?.into(), - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), justification: Self::read_u8(data)?.into(), value: Self::read_string(Self::read_u8(data)?.into(), data)?, enabled: Self::read_bool(data)?, @@ -533,7 +546,7 @@ impl Object { background_colour: Self::read_u8(data)?, font_attributes: Self::read_u16(data)?.try_into()?, options: Self::read_u8(data)?.into(), - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), value: Self::read_u32(data)?, min_value: Self::read_u32(data)?, max_value: Self::read_u32(data)?, @@ -560,15 +573,17 @@ impl Object { id, width: Self::read_u16(data)?, height: Self::read_u16(data)?, - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), value: Self::read_u8(data)?, list_items: Vec::with_capacity(Self::read_u8(data)?.into()), options: Self::read_u8(data)?.into(), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; - o.list_items - .extend(Self::read_objects(data, o.list_items.capacity())?); + o.list_items.extend(Self::read_nullable_object_ids( + data, + o.list_items.capacity(), + )?); o.macro_refs .extend(Self::read_macro_refs(data, o.macro_refs.capacity())?); @@ -586,7 +601,7 @@ impl Object { background_colour: Self::read_u8(data)?, font_attributes: Self::read_u16(data)?.try_into()?, options: Self::read_u8(data)?.into(), - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), justification: Self::read_u8(data)?.into(), value: Self::read_string(Self::read_u16(data)?.into(), data)?, macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), @@ -609,7 +624,7 @@ impl Object { background_colour: Self::read_u8(data)?, font_attributes: Self::read_u16(data)?.try_into()?, options: Self::read_u8(data)?.into(), - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), value: Self::read_u32(data)?, offset: Self::read_i32(data)?, scale: Self::read_f32(data)?, @@ -654,7 +669,7 @@ impl Object { width: Self::read_u16(data)?, height: Self::read_u16(data)?, line_suppression: Self::read_u8(data)?, - fill_attributes: Self::read_u16(data)?.try_into()?, + fill_attributes: Self::read_u16(data)?.into(), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -676,7 +691,7 @@ impl Object { ellipse_type: Self::read_u8(data)?, start_angle: Self::read_u8(data)?, end_angle: Self::read_u8(data)?, - fill_attributes: Self::read_u16(data)?.try_into()?, + fill_attributes: Self::read_u16(data)?.into(), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -695,7 +710,7 @@ impl Object { width: Self::read_u16(data)?, height: Self::read_u16(data)?, line_attributes: Self::read_u16(data)?.try_into()?, - fill_attributes: Self::read_u16(data)?.try_into()?, + fill_attributes: Self::read_u16(data)?.into(), polygon_type: Self::read_u8(data)?, points: Vec::with_capacity(Self::read_u8(data)?.into()), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), @@ -725,7 +740,7 @@ impl Object { end_angle: Self::read_u8(data)?, min_value: Self::read_u16(data)?, max_value: Self::read_u16(data)?, - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), value: Self::read_u16(data)?, macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -750,9 +765,9 @@ impl Object { nr_of_ticks: Self::read_u8(data)?, min_value: Self::read_u16(data)?, max_value: Self::read_u16(data)?, - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), value: Self::read_u16(data)?, - target_value_variable_reference: Self::read_u16(data)?.try_into()?, + target_value_variable_reference: Self::read_u16(data)?.into(), target_value: Self::read_u16(data)?, macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -779,9 +794,9 @@ impl Object { bar_graph_width: Self::read_u16(data)?, min_value: Self::read_u16(data)?, max_value: Self::read_u16(data)?, - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), value: Self::read_u16(data)?, - target_value_variable_reference: Self::read_u16(data)?.try_into()?, + target_value_variable_reference: Self::read_u16(data)?.into(), target_value: Self::read_u16(data)?, macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -884,7 +899,7 @@ impl Object { id, fill_type: Self::read_u8(data)?, fill_colour: Self::read_u8(data)?, - fill_pattern: Self::read_u16(data)?.try_into()?, + fill_pattern: Self::read_u16(data)?.into(), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -917,7 +932,7 @@ impl Object { ) -> Result { let o = ObjectPointer { id, - value: Self::read_u16(data)?.try_into()?, + value: Self::read_u16(data)?.into(), }; Ok(Object::ObjectPointer(o)) @@ -1028,15 +1043,15 @@ impl Object { background_colour: Self::read_u8(data)?, options: Self::read_u8(data)?.into(), name: Self::read_u16(data)?.try_into()?, - window_title: Self::read_u16(data)?.try_into()?, - window_icon: Self::read_u16(data)?.try_into()?, + window_title: Self::read_u16(data)?.into(), + window_icon: Self::read_u16(data)?.into(), objects: Vec::with_capacity(Self::read_u8(data)?.into()), object_refs: Vec::with_capacity(Self::read_u8(data)?.into()), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; o.objects - .extend(Self::read_objects(data, o.objects.capacity())?); + .extend(Self::read_nullable_object_ids(data, o.objects.capacity())?); o.object_refs .extend(Self::read_object_refs(data, o.object_refs.capacity())?); o.macro_refs @@ -1053,13 +1068,13 @@ impl Object { id, options: Self::read_u8(data)?.into(), name: Self::read_u16(data)?.try_into()?, - key_group_icon: Self::read_u16(data)?.try_into()?, + key_group_icon: Self::read_u16(data)?.into(), objects: Vec::with_capacity(Self::read_u8(data)?.into()), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; o.objects - .extend(Self::read_objects(data, o.objects.capacity())?); + .extend(Self::read_object_ids(data, o.objects.capacity())?); o.macro_refs .extend(Self::read_macro_refs(data, o.macro_refs.capacity())?); @@ -1083,9 +1098,9 @@ impl Object { graphics_cursor_y: Self::read_i16(data)?, foreground_colour: Self::read_u8(data)?, background_colour: Self::read_u8(data)?, - font_attributes_object: Self::read_u16(data)?.try_into()?, - line_attributes_object: Self::read_u16(data)?.try_into()?, - fill_attributes_object: Self::read_u16(data)?.try_into()?, + font_attributes_object: Self::read_u16(data)?.into(), + line_attributes_object: Self::read_u16(data)?.into(), + fill_attributes_object: Self::read_u16(data)?.into(), format: Self::read_u8(data)?.into(), options: Self::read_u8(data)?.into(), transparency_colour: Self::read_u8(data)?, @@ -1101,14 +1116,16 @@ impl Object { id, width: Self::read_u16(data)?, height: Self::read_u16(data)?, - variable_reference: Self::read_u16(data)?.try_into()?, + variable_reference: Self::read_u16(data)?.into(), value: Self::read_u8(data)?, list_items: Vec::with_capacity(Self::read_u8(data)?.into()), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; - o.list_items - .extend(Self::read_objects(data, o.list_items.capacity())?); + o.list_items.extend(Self::read_nullable_object_ids( + data, + o.list_items.capacity(), + )?); o.macro_refs .extend(Self::read_macro_refs(data, o.macro_refs.capacity())?); @@ -1170,7 +1187,7 @@ impl Object { }; o.objects - .extend(Self::read_objects(data, o.objects.capacity())?); + .extend(Self::read_nullable_object_ids(data, o.objects.capacity())?); Ok(Object::ExternalObjectDefinition(o)) } @@ -1194,9 +1211,9 @@ impl Object { ) -> Result { let o = ExternalObjectPointer { id, - default_object_id: Self::read_u16(data)?.try_into()?, - external_reference_name_id: Self::read_u16(data)?.try_into()?, - external_object_id: Self::read_u16(data)?.try_into()?, + default_object_id: Self::read_u16(data)?.into(), + external_reference_name_id: Self::read_u16(data)?.into(), + external_object_id: Self::read_u16(data)?.into(), }; Ok(Object::ExternalObjectPointer(o)) @@ -1266,8 +1283,8 @@ impl Object { ) -> Result { let mut o = WorkingSetSpecialControls { id, - id_of_colour_map: Self::read_u16(data)?.try_into()?, - id_of_colour_palette: Self::read_u16(data)?.try_into()?, + id_of_colour_map: Self::read_u16(data)?.into(), + id_of_colour_palette: Self::read_u16(data)?.into(), language_pairs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -1289,7 +1306,7 @@ impl Object { height: Self::read_u16(data)?, scale_type: Self::read_u8(data)?, options: Self::read_u8(data)?.into(), - value: Self::read_u16(data)?, + value: Self::read_u16(data)?.into(), macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; diff --git a/src/object_pool/vt_version.rs b/src/object_pool/vt_version.rs index 16410ab..da1f63a 100644 --- a/src/object_pool/vt_version.rs +++ b/src/object_pool/vt_version.rs @@ -1,5 +1,5 @@ use crate::object_pool::ParseError; -use crate::object_pool::ParseError::UnknownObjectType; +use crate::object_pool::ParseError::UnsupportedVtVersion; #[derive(Debug, Default)] pub enum VtVersion { @@ -39,7 +39,7 @@ impl TryFrom for VtVersion { 4 => Ok(VtVersion::Version4), 5 => Ok(VtVersion::Version5), 6 => Ok(VtVersion::Version6), - _ => Err(UnknownObjectType), + _ => Err(UnsupportedVtVersion), } } } diff --git a/src/object_pool/writer.rs b/src/object_pool/writer.rs index c2edb9d..91a8edb 100644 --- a/src/object_pool/writer.rs +++ b/src/object_pool/writer.rs @@ -1,3 +1,4 @@ +use super::object_id::NullableObjectId; use super::*; use crate::object_pool::colour::Colour; use crate::object_pool::object::{ @@ -84,11 +85,18 @@ impl Object { data } - fn write_objects(data: &mut Vec, objects: &Vec) { + fn write_object_ids(data: &mut Vec, objects: &Vec) { for d in objects { Self::write_u16(data, *d); } } + + fn write_nullable_object_ids(data: &mut Vec, objects: &Vec) { + for d in objects { + Self::write_u16(data, *d); + } + } + fn write_object_refs(data: &mut Vec, object_refs: &Vec) { for d in object_refs { Self::write_u16(data, d.id); @@ -247,7 +255,7 @@ impl Object { Self::write_u8(data, o.objects.len() as u8); Self::write_u8(data, o.macro_refs.len() as u8); - Self::write_objects(data, &o.objects); + Self::write_object_ids(data, &o.objects); Self::write_macro_refs(data, &o.macro_refs); } fn write_key(data: &mut Vec, o: &Key) { @@ -339,7 +347,7 @@ impl Object { Self::write_u8(data, o.options); Self::write_u8(data, o.macro_refs.len() as u8); - Self::write_objects(data, &o.list_items); + Self::write_nullable_object_ids(data, &o.list_items); Self::write_macro_refs(data, &o.macro_refs); } fn write_output_string(data: &mut Vec, o: &OutputString) { @@ -628,7 +636,7 @@ impl Object { Self::write_u8(data, o.object_refs.len() as u8); Self::write_u8(data, o.macro_refs.len() as u8); - Self::write_objects(data, &o.objects); + Self::write_nullable_object_ids(data, &o.objects); Self::write_object_refs(data, &o.object_refs); Self::write_macro_refs(data, &o.macro_refs); } @@ -641,7 +649,7 @@ impl Object { Self::write_u8(data, o.objects.len() as u8); Self::write_u8(data, o.macro_refs.len() as u8); - Self::write_objects(data, &o.objects); + Self::write_object_ids(data, &o.objects); Self::write_macro_refs(data, &o.macro_refs); } fn write_graphics_context(data: &mut Vec, o: &GraphicsContext) { @@ -675,7 +683,7 @@ impl Object { Self::write_u8(data, o.list_items.len() as u8); Self::write_u8(data, o.macro_refs.len() as u8); - Self::write_objects(data, &o.list_items); + Self::write_nullable_object_ids(data, &o.list_items); Self::write_macro_refs(data, &o.macro_refs); } fn write_extended_input_attributes(data: &mut Vec, o: &ExtendedInputAttributes) { @@ -705,7 +713,7 @@ impl Object { Self::write_name(data, o.name); Self::write_u8(data, o.objects.len() as u8); - Self::write_objects(data, &o.objects); + Self::write_nullable_object_ids(data, &o.objects); } fn write_external_reference_name(data: &mut Vec, o: &ExternalReferenceName) { Self::write_u16(data, o.id);