use thiserror::Error as ThisError;
-use crate::raw::{VarType, self};
+use crate::{
+ cooked::VarWidth,
+ raw::{self, VarType},
+};
#[derive(ThisError, Debug)]
pub enum Error {
- #[error("Unknown format type {value}")]
+ #[error("Unknown format type {value}.")]
UnknownFormat { value: u16 },
#[error("Output format {0} specifies width {}, but {} requires an even width.", .0.w, .0.format)]
#[error("Numeric variable is not compatible with string format {0}.")]
UnnamedVariableNotCompatibleWithStringFormat(Format),
- #[error("String variable {variable} is not compatible with numeric format {format}.")]
- NamedVariableNotCompatibleWithNumericFormat { variable: String, format: Format },
-
- #[error("Numeric variable {variable} is not compatible with string format {format}.")]
- NamedVariableNotCompatibleWithStringFormat { variable: String, format: Format },
-
#[error("String variable {variable} with width {width} is not compatible with format {bad_spec}. Use format {good_spec} instead.")]
NamedStringVariableBadSpecWidth {
variable: String,
AHex,
}
-pub const MAX_STRING: Width = 32767;
-
pub type Width = u16;
pub type SignedWidth = i16;
match self {
Self::P | Self::PK | Self::PIBHex | Self::RBHex => 16,
Self::IB | Self::PIB | Self::RB => 8,
- Self::A => MAX_STRING,
- Self::AHex => MAX_STRING * 2,
+ Self::A => 32767,
+ Self::AHex => 32767 * 2,
_ => 40,
}
}
pub fn var_type(self) -> VarType {
match self {
Self::A | Self::AHex => VarType::String,
- _ => VarType::Number,
+ _ => VarType::Numeric,
}
}
- pub fn check_type_compatibility(
- self,
- variable: Option<&str>,
- var_type: VarType,
- ) -> Result<(), Error> {
+ /// Checks whether this format is valid for a variable with the given
+ /// `var_type`.
+ pub fn check_type_compatibility(self, var_type: VarType) -> Result<(), Error> {
let my_type = self.var_type();
match (my_type, var_type) {
- (VarType::Number, VarType::String) => {
- if let Some(variable) = variable {
- Err(Error::NamedVariableNotCompatibleWithNumericFormat {
- variable: variable.into(),
- format: self,
- })
- } else {
- Err(Error::UnnamedVariableNotCompatibleWithNumericFormat(self))
- }
+ (VarType::Numeric, VarType::String) => {
+ Err(Error::UnnamedVariableNotCompatibleWithNumericFormat(self))
}
- (VarType::String, VarType::Number) => {
- if let Some(variable) = variable {
- Err(Error::NamedVariableNotCompatibleWithStringFormat {
- variable: variable.into(),
- format: self,
- })
- } else {
- Err(Error::UnnamedVariableNotCompatibleWithStringFormat(self))
- }
+ (VarType::String, VarType::Numeric) => {
+ Err(Error::UnnamedVariableNotCompatibleWithStringFormat(self))
}
_ => Ok(()),
}
self.d
}
- pub fn default_for_width(w: Width) -> Self {
- match w {
- 0 => Spec { format: Format::F, w: 8, d: 2 },
- _ => Spec { format: Format::A, w: w, d: 0 },
+ pub fn default_for_width(var_width: VarWidth) -> Self {
+ match var_width {
+ VarWidth::Numeric => Spec {
+ format: Format::F,
+ w: 8,
+ d: 2,
+ },
+ VarWidth::String(w) => Spec {
+ format: Format::A,
+ w,
+ d: 0,
+ },
}
}
Self { format, w, d }
}
- pub fn var_width(self) -> Width {
+ pub fn var_width(self) -> VarWidth {
match self.format {
- Format::A => self.w,
- Format::AHex => self.w / 2,
- _ => 0,
+ Format::A => VarWidth::String(self.w),
+ Format::AHex => VarWidth::String(self.w / 2),
+ _ => VarWidth::Numeric,
}
}
self.format.var_type()
}
- pub fn check_width_compatibility(self, variable: Option<&str>, w: Width) -> Result<Self, Error> {
- self.format.check_type_compatibility(variable, self.var_type())?;
- let expected_width = self.var_width();
- if w != expected_width {
- let bad_spec = self;
- let good_spec = if self.format == Format::A {
- Spec { w, ..self }
- } else {
- Spec { w: w * 2, ..self }
- };
- if let Some(variable) = variable {
- Err(Error::NamedStringVariableBadSpecWidth {
- variable: variable.into(),
- width: w,
- bad_spec,
- good_spec,
- })
- } else {
- Err(Error::UnnamedStringVariableBadSpecWidth {
+ /// Checks whether this format specification is valid for a variable with
+ /// width `var_width`.
+ pub fn check_width_compatibility(self, var_width: VarWidth) -> Result<Self, Error> {
+ // Verify that the format is right for the variable's type.
+ self.format
+ .check_type_compatibility(var_width.into())?;
+
+ if let VarWidth::String(w) = var_width {
+ if var_width != self.var_width() {
+ let bad_spec = self;
+ let good_spec = if self.format == Format::A {
+ Spec { w, ..self }
+ } else {
+ Spec { w: w * 2, ..self }
+ };
+ return Err(Error::UnnamedStringVariableBadSpecWidth {
width: w,
bad_spec,
good_spec,
- })
+ });
}
- } else {
- Ok(self)
}
+
+ Ok(self)
}
}