-use std::{cell::RefCell, ops::Range, rc::Rc, collections::HashMap};
+use std::{cell::RefCell, collections::HashMap, ops::Range, rc::Rc};
use crate::{
dictionary::{Dictionary, VarWidth, Variable},
#[error("Dictionary index {0} refers to a long string continuation.")]
DictIndexIsContinuation(usize),
+ #[error("At offset {offset:#x}, one or more variable indexes for value labels referred to long string continuation records: {indexes:?}")]
+ LongStringContinuationIndexes { offset: u64, indexes: Vec<u32> },
+
+ #[error(
+ "At offsets {:#x}...{:#x}, record types 3 and 4 may not add value labels to one or more long string variables: {variables:?}", .offsets.start, .offsets.end
+ )]
+ InvalidLongStringValueLabels {
+ offsets: Range<u64>,
+ variables: Vec<Identifier>,
+ },
+
#[error("Variables associated with value label are not all of identical type. Variable {numeric_var} is numeric, but variable {string_var} is string.")]
ValueLabelsDifferentTypes {
numeric_var: Identifier,
string_var: Identifier,
},
- #[error(
- "Value labels may not be added to long string variable {0} using record types 3 or 4."
- )]
- InvalidLongStringValueLabel(Identifier),
-
#[error("Invalid multiple response set name. {0}")]
InvalidMrSetName(IdError),
assert_eq!(var_index_map.insert(value_index, dict_index), None);
}
+ for record in headers.value_label.drain(..) {
+ let mut dict_indexes = Vec::with_capacity(record.dict_indexes.len());
+ let mut continuation_indexes = Vec::new();
+ let mut long_string_variables = Vec::new();
+ for value_index in record.dict_indexes.iter() {
+ if let Some(dict_index) = var_index_map.get(&(*value_index as usize - 1)) {
+ let variable = &dictionary.variables[*dict_index];
+ if variable.width.is_long_string() {
+ long_string_variables.push(variable.name.clone());
+ } else {
+ dict_indexes.push(*dict_index);
+ }
+ } else {
+ continuation_indexes.push(*value_index);
+ }
+ }
+ if !continuation_indexes.is_empty() {
+ warn(Error::LongStringContinuationIndexes {
+ offset: record.offsets.start,
+ indexes: continuation_indexes,
+ });
+ }
+ if !long_string_variables.is_empty() {
+ warn(Error::InvalidLongStringValueLabels {
+ offsets: record.offsets.clone(),
+ variables: long_string_variables,
+ });
+ }
+ }
+
let metadata = Metadata::decode(&headers, warn);
Ok((dictionary, metadata))
}
BadRecordType { offset: u64, rec_type: u32 },
#[error("In variable record starting at offset {start_offset:#x}, variable width is not in the valid range -1 to 255.")]
- BadVariableWidth {
- start_offset: u64,
- width: i32,
- },
+ BadVariableWidth { start_offset: u64, width: i32 },
#[error("In variable record starting at offset {start_offset:#x}, variable label code {code} at offset {code_offset:#x} is not 0 or 1.")]
BadVariableLabelCode {
max: Self::MAX_INDEXES,
});
}
-
+
let index_offset = r.stream_position()?;
let mut dict_indexes = Vec::with_capacity(n as usize);
let mut invalid_indexes = Vec::new();