endian::Endian,
format::{Error as FormatError, Spec, UncheckedSpec},
identifier::{Error as IdError, Identifier},
- raw::{self, RawStr, RawString, VarType},
+ raw::{self, RawStr, RawString, VarType, RawDocumentLine},
};
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use encoding_rs::{DecoderResult, Encoding};
header: Option<&'a raw::HeaderRecord<RawString>>,
variables: Vec<&'a raw::VariableRecord<RawString, RawStr<8>>>,
value_labels: Vec<&'a raw::ValueLabelRecord<RawStr<8>, RawString>>,
- document: Option<&'a raw::DocumentRecord>,
+ document: Option<&'a raw::DocumentRecord<RawDocumentLine>>,
integer_info: Option<&'a raw::IntegerInfoRecord>,
float_info: Option<&'a raw::FloatInfoRecord>,
variable_sets: Vec<&'a raw::TextRecord>,
pub struct DocumentRecord(Vec<String>);
impl TryDecode for DocumentRecord {
- type Input = crate::raw::DocumentRecord;
+ type Input = crate::raw::DocumentRecord<RawDocumentLine>;
fn try_decode(
decoder: &mut Decoder,
Header(HeaderRecord<RawString>),
Variable(VariableRecord<RawString, RawStr<8>>),
ValueLabel(ValueLabelRecord<RawStr<8>, RawString>),
- Document(DocumentRecord),
+ Document(DocumentRecord<RawDocumentLine>),
IntegerInfo(IntegerInfoRecord),
FloatInfo(FloatInfoRecord),
VariableSets(TextRecord),
}
impl Decoder {
- fn decode<'a>(&self, input: &'a RawString) -> Cow<'a, str> {
- let (output, malformed) = self.encoding.decode_without_bom_handling(&input.0);
+ fn decode_slice<'a>(&self, input: &'a [u8]) -> Cow<'a, str> {
+ let (output, malformed) = self.encoding.decode_without_bom_handling(input);
if malformed {
(self.warn)(Error::MalformedString {
encoding: self.encoding.name().into(),
}
output
}
+
+ fn decode<'a>(&self, input: &'a RawString) -> Cow<'a, str> {
+ self.decode_slice(input.0.as_slice())
+ }
/// Returns `input` decoded from `self.encoding` into UTF-8 such that
/// re-encoding the result back into `self.encoding` will have exactly the
}
#[derive(Clone, Debug)]
-pub struct DocumentRecord {
+pub struct DocumentRecord<S>
+where
+ S: Debug,
+{
pub offsets: Range<u64>,
/// The document, as an array of 80-byte lines.
- pub lines: Vec<DocumentLine>,
+ pub lines: Vec<S>,
}
-pub type DocumentLine = RawStr<{ DocumentRecord::LINE_LEN }>;
+pub type RawDocumentLine = RawStr<DOC_LINE_LEN>;
-impl DocumentRecord {
- /// Length of a line in a document. Document lines are fixed-length and
- /// padded on the right with spaces.
- pub const LINE_LEN: usize = 80;
+/// Length of a line in a document. Document lines are fixed-length and
+/// padded on the right with spaces.
+pub const DOC_LINE_LEN: usize = 80;
+impl DocumentRecord<RawDocumentLine> {
/// Maximum number of lines we will accept in a document. This is simply
/// the maximum number that will fit in a 32-bit space.
- pub const MAX_LINES: usize = i32::MAX as usize / Self::LINE_LEN;
+ pub const MAX_LINES: usize = i32::MAX as usize / DOC_LINE_LEN;
fn read<R: Read + Seek>(r: &mut R, endian: Endian) -> Result<Record, Error> {
let start_offset = r.stream_position()?;
} else {
let mut lines = Vec::with_capacity(n);
for _ in 0..n {
- lines.push(RawStr::<{ DocumentRecord::LINE_LEN }>(read_bytes(r)?));
+ lines.push(RawStr(read_bytes(r)?));
}
let end_offset = r.stream_position()?;
Ok(Record::Document(DocumentRecord {
}))
}
}
+
+ fn decode<'a>(&'a self, decoder: &Decoder) -> DocumentRecord<Cow<'a, str>> {
+ DocumentRecord {
+ offsets: self.offsets.clone(),
+ lines: self.lines.iter().map(|s| decoder.decode_slice(&s.0)).collect(),
+ }
+ }
}
-impl Header for DocumentRecord {
+impl<S> Header for DocumentRecord<S>
+where
+ S: Debug,
+{
fn offsets(&self) -> Range<u64> {
self.offsets.clone()
}