// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
-use anyhow::{anyhow, Result as AnyResult};
+use anyhow::{Result as AnyResult, anyhow};
use std::{
collections::{BTreeMap, HashSet, VecDeque},
env::var_os,
- fs::{read_to_string, File},
+ fs::{File, read_to_string},
io::{Error as IoError, Write},
path::{Path, PathBuf},
};
(99998, Source::Codepage, "replacement"),
(99999, Source::Codepage, "x-user-defined"),
] {
- assert!(codepages
- .insert(codepage, [(source, vec![name])].into_iter().collect())
- .is_none());
+ assert!(
+ codepages
+ .insert(codepage, [(source, vec![name])].into_iter().collect())
+ .is_none()
+ );
}
let output_file_name = Path::new(&var_os("OUT_DIR").unwrap()).join("encodings.rs");
use data_list::data_list_command;
use descriptives::descriptives_command;
use either::Either;
-use flagset::{flags, FlagSet};
+use flagset::{FlagSet, flags};
use pspp_derive::FromTokens;
use crate::{
identifier::Identifier,
integer::ToInteger,
lex::{
+ Punct, Token,
command_name::CommandMatcher,
lexer::{LexToken, TokenSlice},
- Punct, Token,
},
message::{Diagnostic, Diagnostics},
};
impl Debug for Expression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- if self.1 .0.is_empty() {
+ if self.1.0.is_empty() {
self.0.fmt(f)
} else {
write!(f, "(")?;
self.0.fmt(f)?;
- for (operator, operand) in &self.1 .0 {
+ for (operator, operand) in &self.1.0 {
if operator.is_left() {
write!(f, " + ")?;
} else {
impl Debug for MulExpression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- if self.1 .0.is_empty() {
+ if self.1.0.is_empty() {
self.0.fmt(f)
} else {
write!(f, "(")?;
self.0.fmt(f)?;
- for (operator, operand) in &self.1 .0 {
+ for (operator, operand) in &self.1.0 {
if operator.is_left() {
write!(f, " * ")?;
} else {
impl Debug for PowExpression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- if self.1 .0.is_empty() {
+ if self.1.0.is_empty() {
self.0.fmt(f)
} else {
write!(f, "(")?;
self.0.fmt(f)?;
- for (_operator, operand) in &self.1 .0 {
+ for (_operator, operand) in &self.1.0 {
write!(f, " ** {operand:?}")?;
}
write!(f, ")")
use std::{
fs::File,
- io::{stdout, Write},
+ io::{Write, stdout},
path::{Path, PathBuf},
};
-use anyhow::{anyhow, bail, Error as AnyError, Result};
+use anyhow::{Error as AnyError, Result, anyhow, bail};
use chrono::{Datelike, NaiveTime, Timelike};
use clap::{Args, ValueEnum};
use csv::Writer;
file::FileType,
format::{DisplayPlain, Type},
por::PortableFile,
- sys::{raw::records::Compression, ReadOptions, WriteOptions},
+ sys::{ReadOptions, WriteOptions, raw::records::Compression},
util::ToSmallString,
variable::Variable,
};
#![cfg_attr(not(test), warn(missing_docs))]
use aes::{
- cipher::{generic_array::GenericArray, BlockDecrypt, KeyInit},
Aes256, Aes256Dec,
+ cipher::{BlockDecrypt, KeyInit, generic_array::GenericArray},
};
use cmac::{Cmac, Mac};
use smallvec::SmallVec;
};
use thiserror::Error as ThisError;
-use binrw::{io::NoSeek, BinRead};
+use binrw::{BinRead, io::NoSeek};
/// Error reading an encrypted file.
#[derive(Clone, Debug, ThisError)]
_ => {
return Err(Error::UnknownFileType(
header.file_type.iter().map(|b| *b as char).collect(),
- ))
+ ));
}
};
let mut first_block = [0; 16];
str::from_utf8,
};
-use encoding_rs::{mem::decode_latin1, Encoding, UTF_8};
+use encoding_rs::{Encoding, UTF_8, mem::decode_latin1};
use itertools::Itertools;
use ordered_float::OrderedFloat;
use serde::{
- ser::{SerializeSeq, SerializeTupleVariant},
Serialize,
+ ser::{SerializeSeq, SerializeTupleVariant},
};
use crate::{
dictionary::Dictionary,
format::DisplayPlain,
output::{
- pivot::{Axis3, Dimension, Group, PivotTable, Value},
Item, Text,
+ pivot::{Axis3, Dimension, Group, PivotTable, Value},
},
variable::{VarType, VarWidth},
};
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
-use anyhow::{anyhow, Result};
+use anyhow::{Result, anyhow};
use clap::Args;
use pspp::crypto::EncryptedFile;
use std::{fs::File, path::PathBuf};
use core::str;
use std::{
borrow::Cow,
- collections::{btree_set, BTreeSet, HashSet},
+ collections::{BTreeSet, HashSet, btree_set},
ops::{Bound, Index, RangeBounds, RangeInclusive},
};
use enum_map::{Enum, EnumMap};
use indexmap::IndexSet;
use serde::{
- ser::{SerializeMap, SerializeSeq, SerializeStruct},
Serialize,
+ ser::{SerializeMap, SerializeSeq, SerializeStruct},
};
use smallvec::SmallVec;
use thiserror::Error as ThisError;
}
pub fn add_variable_set(&mut self, set: DictIndexVariableSet) {
- assert!(set
- .variables
- .iter()
- .all(|dict_index| *dict_index < self.variables.len()));
+ assert!(
+ set.variables
+ .iter()
+ .all(|dict_index| *dict_index < self.variables.len())
+ );
self.variable_sets.push(set);
}
/// Counted value {value} has width {width}, but it must be no wider than
/// {max_width}, the width of the narrowest variable in multiple response
/// set {mr_set}.
- #[error("Counted value {value} has width {width}, but it must be no wider than {max_width}, the width of the narrowest variable in multiple response set {mr_set}.")]
+ #[error(
+ "Counted value {value} has width {width}, but it must be no wider than {max_width}, the width of the narrowest variable in multiple response set {mr_set}."
+ )]
TooWideMDGroupCountedValue {
/// Multiple response set name.
mr_set: Identifier,
};
use chrono::{Datelike, Local};
-use enum_iterator::{all, Sequence};
+use enum_iterator::{Sequence, all};
use enum_map::{Enum, EnumMap};
use serde::{Deserialize, Serialize};
use thiserror::Error as ThisError;
#[error("Numeric variable is not compatible with string format {0}.")]
UnnamedVariableNotCompatibleWithStringFormat(Type),
- #[error("String variable {variable} with width {width} is not compatible with format {bad_spec}. Use format {good_spec} instead.")]
+ #[error(
+ "String variable {variable} with width {width} is not compatible with format {bad_spec}. Use format {good_spec} instead."
+ )]
NamedStringVariableBadSpecWidth {
variable: String,
width: Width,
good_spec: Format,
},
- #[error("String variable with width {width} is not compatible with format {bad_spec}. Use format {good_spec} instead.")]
+ #[error(
+ "String variable with width {width} is not compatible with format {bad_spec}. Use format {good_spec} instead."
+ )]
UnnamedStringVariableBadSpecWidth {
width: Width,
bad_spec: Format,
use std::{fmt::Write, fs::File, io::BufRead, path::Path};
-use binrw::{io::BufReader, Endian};
+use binrw::{Endian, io::BufReader};
use encoding_rs::UTF_8;
use itertools::Itertools;
use smallstr::SmallString;
use crate::{
data::{ByteString, Datum, WithEncoding},
- format::{AbstractFormat, Epoch, Format, Settings, Type, UncheckedFormat, CC},
- lex::{scan::StringScanner, segment::Syntax, Punct, Token},
+ format::{AbstractFormat, CC, Epoch, Format, Settings, Type, UncheckedFormat},
+ lex::{Punct, Token, scan::StringScanner, segment::Syntax},
settings::EndianSettings,
};
.display(format)
.to_string();
assert!(
- formatted == expect,
- "formatting {}:{line_number} as {format}:\n actual: {formatted:?}\nexpected: {expect:?}",
- input_filename.display()
- );
+ formatted == expect,
+ "formatting {}:{line_number} as {format}:\n actual: {formatted:?}\nexpected: {expect:?}",
+ input_filename.display()
+ );
}
}
// this program. If not, see <http://www.gnu.org/licenses/>.
use crate::{
- calendar::{calendar_gregorian_to_offset, DateError},
+ calendar::{DateError, calendar_gregorian_to_offset},
data::{ByteString, Datum, EncodedString, OwnedDatum, RawString, WithEncoding},
endian::FromBytes,
format::{DateTemplate, Decimals, Settings, TemplateItem, Type},
InvalidWeek(i32),
/// Unrecognized month format.
- #[error("Unrecognized month format. Months may be specified as Arabic or Roman numerals or as at least 3 letters of their English names.")]
+ #[error(
+ "Unrecognized month format. Months may be specified as Arabic or Roman numerals or as at least 3 letters of their English names."
+ )]
InvalidMonth,
/// Delimiter expected between fields in time.
InvalidMinute(i32),
/// Invalid weekday name.
- #[error("Unrecognized weekday name. At least the first two letters of an English weekday name must be specified.")]
+ #[error(
+ "Unrecognized weekday name. At least the first two letters of an English weekday name must be specified."
+ )]
InvalidWeekdayName,
/// Expected character.
calendar::{days_in_month, is_leap_year},
data::{ByteStr, Datum, EncodedString, OwnedDatum, RawString},
format::{
- parse::{ParseError, ParseErrorKind, Sign},
Epoch, Format, Settings as FormatSettings, Type,
+ parse::{ParseError, ParseErrorKind, Sign},
},
settings::EndianSettings,
};
#[error("\"!\" is not a valid identifier.")]
Bang,
- #[error("{string:?} may not be used as an identifier because it begins with disallowed character {c:?}.")]
+ #[error(
+ "{string:?} may not be used as an identifier because it begins with disallowed character {c:?}."
+ )]
BadFirstCharacter { string: String, c: char },
#[error(
)]
BadLaterCharacter { string: String, c: char },
- #[error("Identifier \"{id}\" is {length} bytes in the encoding in use ({encoding}), which exceeds the {max}-byte limit.")]
+ #[error(
+ "Identifier \"{id}\" is {length} bytes in the encoding in use ({encoding}), which exceeds the {max}-byte limit."
+ )]
TooLong {
id: String,
length: usize,
max: usize,
},
- #[error("\"{id}\" may not be used as an identifier because the encoding in use ({encoding}) cannot represent \"{c}\".")]
+ #[error(
+ "\"{id}\" may not be used as an identifier because the encoding in use ({encoding}) cannot represent \"{c}\"."
+ )]
NotEncodable {
id: String,
encoding: &'static str,
use crate::{
lex::scan::merge_tokens,
- macros::{macro_tokens_to_syntax, MacroSet, ParseStatus, Parser},
+ macros::{MacroSet, ParseStatus, Parser, macro_tokens_to_syntax},
message::{Category, Diagnostic, Location, Point, Severity},
settings::Settings,
};
use std::cmp::Ordering;
use crate::{
- identifier::{id_match, id_match_n, IdentifierChar},
+ identifier::{IdentifierChar, id_match, id_match_n},
prompt::PromptStyle,
};
use bitflags::bitflags;
-use super::command_name::{command_match, COMMAND_NAMES};
+use super::command_name::{COMMAND_NAMES, command_match};
/// Syntax variant.
///
};
match c {
'!' if strip_prefix_ignore_ascii_case(input, "!ENDDEFINE").is_some() => {
- return Some(input)
+ return Some(input);
}
'\'' | '"' => {
let index = rest.find(c)?;
#[cfg(unix)]
mod inner {
use std::{
- ffi::{c_int, CStr, CString},
+ ffi::{CStr, CString, c_int},
ptr::null,
};
- use libc::{self, nl_langinfo, setlocale, CODESET, LC_CTYPE};
+ use libc::{self, CODESET, LC_CTYPE, nl_langinfo, setlocale};
unsafe fn string_from_pointer(s: *const i8) -> Option<String> {
if s.is_null() {
#[cfg(windows)]
mod inner {
- use libc::{setlocale, LC_CTYPE};
+ use libc::{LC_CTYPE, setlocale};
use std::ffi::{CStr, CString};
use windows_sys::Win32::Globalization::GetACP;
use crate::{
identifier::Identifier,
lex::{
+ Punct, Token,
scan::{ScanError, StringScanner, StringSegmenter},
segment::Syntax,
- Punct, Token,
},
message::Location,
settings::Settings,
BadNumericMacroExpression(String),
/// Too many iteration for list-based loop.
- #[error("`!DO` loop over list exceeded maximum number of iterations {0}. (Use `SET MITERATE` to change the limit.)")]
+ #[error(
+ "`!DO` loop over list exceeded maximum number of iterations {0}. (Use `SET MITERATE` to change the limit.)"
+ )]
MiterateList(usize),
/// Too many iteration for numerical loop.
- #[error("Numerical `!DO` loop exceeded maximum number of iterations {0}. (Use `SET MITERATE` to change the limit.)")]
+ #[error(
+ "Numerical `!DO` loop exceeded maximum number of iterations {0}. (Use `SET MITERATE` to change the limit.)"
+ )]
MiterateNumeric(usize),
/// Expecting `!TO` in numerical `!DO` loop.
};
use cairo::{Context, PdfSurface};
-use enum_map::{enum_map, EnumMap};
+use enum_map::{EnumMap, enum_map};
use pango::SCALE;
use serde::{Deserialize, Serialize};
use crate::output::{
+ Item,
cairo::{
- fsm::{parse_font_style, CairoFsmStyle},
+ fsm::{CairoFsmStyle, parse_font_style},
pager::{CairoPageStyle, CairoPager},
},
driver::Driver,
page::PageSetup,
pivot::{Color, Coord2, FontStyle},
- Item,
};
use crate::output::pivot::Axis2;
use std::{cmp::min, f64::consts::PI, fmt::Write, ops::DerefMut, sync::Arc};
use cairo::Context;
-use enum_map::{enum_map, EnumMap};
+use enum_map::{EnumMap, enum_map};
use itertools::Itertools;
use pango::{
- parse_markup, AttrFloat, AttrFontDesc, AttrInt, AttrList, Attribute, FontDescription, FontMask,
- Layout, Underline, Weight, SCALE, SCALE_SMALL,
+ AttrFloat, AttrFontDesc, AttrInt, AttrList, Attribute, FontDescription, FontMask, Layout,
+ SCALE, SCALE_SMALL, Underline, Weight, parse_markup,
};
use pangocairo::functions::show_layout;
-use smallvec::{smallvec, SmallVec};
+use smallvec::{SmallVec, smallvec};
use crate::output::cairo::{horz_align_to_pango, px_to_xr, xr_to_pt};
use crate::output::pivot::{Axis2, BorderStyle, Coord2, FontStyle, HorzAlign, Rect2, Stroke};
use crate::output::render::{Device, Extreme, Pager, Params};
use crate::output::table::DrawCell;
-use crate::output::{pivot::Color, table::Content};
use crate::output::{Details, Item};
+use crate::output::{pivot::Color, table::Content};
/// Width of an ordinary line.
const LINE_WIDTH: usize = LINE_SPACE / 2;
use pango::{FontDescription, Layout};
use crate::output::{
+ Item, ItemCursor,
cairo::{
fsm::{CairoFsm, CairoFsmStyle},
horz_align_to_pango, xr_to_pt,
},
page::Heading,
pivot::Axis2,
- Item, ItemCursor,
};
#[derive(Clone, Debug)]
};
use serde::{
- de::{Unexpected, Visitor},
Deserialize, Deserializer, Serialize,
+ de::{Unexpected, Visitor},
};
use crate::output::pivot::Coord2;
-use super::{driver::Driver, pivot::PivotTable, table::Table, Details, Item, TextType};
+use super::{Details, Item, TextType, driver::Driver, pivot::PivotTable, table::Table};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CsvConfig {
text::{TextConfig, TextDriver},
};
-use super::{page::PageSetup, Item};
+use super::{Item, page::PageSetup};
// An output driver.
pub trait Driver {
use smallstr::SmallString;
use crate::output::{
+ Details, Item,
driver::Driver,
pivot::{Axis2, BorderStyle, Color, Coord2, HorzAlign, PivotTable, Rect2, Stroke, VertAlign},
table::{DrawCell, Table},
- Details, Item,
};
#[derive(Clone, Debug, Deserialize, Serialize)]
use serde::{Deserialize, Serialize};
-use super::{driver::Driver, Item};
+use super::{Item, driver::Driver};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct JsonConfig {
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
-use enum_map::{enum_map, EnumMap};
+use enum_map::{EnumMap, enum_map};
use serde::{Deserialize, Serialize};
use super::pivot::{Axis2, HorzAlign};
collections::HashMap,
fmt::{Debug, Display, Write},
io::Read,
- iter::{once, repeat, repeat_n, FusedIterator},
+ iter::{FusedIterator, once, repeat, repeat_n},
ops::{Index, IndexMut, Not, Range, RangeInclusive},
- str::{from_utf8, FromStr, Utf8Error},
+ str::{FromStr, Utf8Error, from_utf8},
sync::{Arc, OnceLock},
};
use binrw::Error as BinError;
use chrono::NaiveDateTime;
pub use color::ParseError as ParseColorError;
-use color::{palette::css::TRANSPARENT, AlphaColor, Rgba8, Srgb};
+use color::{AlphaColor, Rgba8, Srgb, palette::css::TRANSPARENT};
use enum_iterator::Sequence;
-use enum_map::{enum_map, Enum, EnumMap};
+use enum_map::{Enum, EnumMap, enum_map};
use look_xml::TableProperties;
-use quick_xml::{de::from_str, DeError};
+use quick_xml::{DeError, de::from_str};
use serde::{
+ Deserialize, Serialize, Serializer,
de::Visitor,
ser::{SerializeMap, SerializeStruct},
- Deserialize, Serialize, Serializer,
};
use smallstr::SmallString;
use smallvec::SmallVec;
use std::{fmt::Debug, num::ParseFloatError, str::FromStr};
use enum_map::enum_map;
-use serde::{de::Visitor, Deserialize};
+use serde::{Deserialize, de::Visitor};
use crate::{
format::Decimal,
use std::{iter::zip, ops::Range, sync::Arc};
-use enum_map::{enum_map, EnumMap};
+use enum_map::{EnumMap, enum_map};
use itertools::Itertools;
use crate::output::{
use enum_map::EnumMap;
use crate::output::{
+ Details, Item,
cairo::{CairoConfig, CairoDriver},
driver::Driver,
html::HtmlDriver,
Look, PivotTable, RowColBorder, Stroke,
},
spv::SpvDriver,
- Details, Item,
};
use super::{Axis3, Value};
};
use super::{Area, BorderStyle, Color, HorzAlign, Look, Stroke, VertAlign};
-use binrw::{binread, BinRead, BinResult, Error as BinError};
+use binrw::{BinRead, BinResult, Error as BinError, binread};
use enum_map::enum_map;
#[binread]
use std::ops::Range;
use std::sync::Arc;
-use enum_map::{enum_map, Enum, EnumMap};
+use enum_map::{Enum, EnumMap, enum_map};
use itertools::interleave;
use num::Integer;
use smallvec::SmallVec;
overflow[a][1] +=
pixel1 + self.axis_width(a, cell_ofs(z1)..cell_ofs(cell.rect[a].end));
}
- assert!(overflows
- .insert(s.coord_to_subpage(cell.rect.top_left()), overflow)
- .is_none());
+ assert!(
+ overflows
+ .insert(s.coord_to_subpage(cell.rect.top_left()), overflow)
+ .is_none()
+ );
}
z += cell.rect[b].len();
}
let mut overflow = self.overflows.get(&d).cloned().unwrap_or_default();
overflow[a][1] +=
pixel1 + self.axis_width(a, cell_ofs(z1)..cell_ofs(cell.rect[a].end));
- assert!(overflows
- .insert(s.coord_to_subpage(cell.rect.top_left()), overflow)
- .is_none());
+ assert!(
+ overflows
+ .insert(s.coord_to_subpage(cell.rect.top_left()), overflow)
+ .is_none()
+ );
}
z += cell.rect[b].len();
}
.into_iter()
.map(
|(rule, present)| {
- if present {
- line_widths[rule]
- } else {
- 0
- }
+ if present { line_widths[rule] } else { 0 }
},
)
.max()
use chrono::Utc;
use enum_map::EnumMap;
use quick_xml::{
- events::{attributes::Attribute, BytesText},
- writer::Writer as XmlWriter,
ElementWriter,
+ events::{BytesText, attributes::Attribute},
+ writer::Writer as XmlWriter,
};
use serde::{Deserialize, Serialize};
-use zip::{result::ZipResult, write::SimpleFileOptions, ZipWriter};
+use zip::{ZipWriter, result::ZipResult, write::SimpleFileOptions};
use crate::{
format::{Format, Type},
output::{
+ Item, Text,
driver::Driver,
page::{Heading, PageSetup},
pivot::{
Footnotes, Group, HeadingRegion, HorzAlign, LabelPosition, Leaf, PivotTable,
RowColBorder, Stroke, Value, ValueInner, ValueStyle, VertAlign,
},
- Item, Text,
},
settings::Show,
util::ToSmallString,
use std::{ops::Range, sync::Arc};
-use enum_map::{enum_map, EnumMap};
+use enum_map::{EnumMap, enum_map};
use ndarray::{Array, Array2};
use crate::output::pivot::{Coord2, DisplayValue, Footnote, HorzAlign, ValueInner};
sync::{Arc, LazyLock},
};
-use enum_map::{enum_map, Enum, EnumMap};
+use enum_map::{Enum, EnumMap, enum_map};
use serde::{Deserialize, Serialize};
-use unicode_linebreak::{linebreaks, BreakOpportunity};
+use unicode_linebreak::{BreakOpportunity, linebreaks};
use unicode_width::UnicodeWidthStr;
use crate::output::{render::Extreme, table::DrawCell, text_line::Emphasis};
use super::{
+ Details, Item,
driver::Driver,
pivot::{Axis2, BorderStyle, Coord2, HorzAlign, PivotTable, Rect2, Stroke},
render::{Device, Pager, Params},
table::Content,
- text_line::{clip_text, TextLine},
- Details, Item,
+ text_line::{TextLine, clip_text},
};
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
fn test_line_breaks(input: &str, width: usize, expected: Vec<&str>) {
let actual = new_line_breaks(input, width).collect::<Vec<_>>();
if expected != actual {
- panic!("filling {input:?} to {width} columns:\nexpected: {expected:?}\nactual: {actual:?}");
+ panic!(
+ "filling {input:?} to {width} columns:\nexpected: {expected:?}\nactual: {actual:?}"
+ );
}
}
#[test]
use encoding_rs::WINDOWS_1252;
use indexmap::set::MutableValues;
use num::{Bounded, NumCast};
-use serde::{ser::SerializeSeq, Serialize, Serializer};
+use serde::{Serialize, Serializer, ser::SerializeSeq};
use crate::{
data::{ByteString, Case, Datum, RawString, WithEncoding},
use crate::{
data::cases_to_output,
output::{
- pivot::{tests::assert_lines_eq, PivotTable},
Details, Item, Text,
+ pivot::{PivotTable, tests::assert_lines_eq},
},
por::{PortableFile, ReadPad},
};
b"abcdefghijklmnop\r\n0123456789\r\n",
)))
.lines();
- assert_eq!(lines.next().unwrap().unwrap(), "abcdefghijklmnop 0123456789 ");
+ assert_eq!(
+ lines.next().unwrap().unwrap(),
+ "abcdefghijklmnop 0123456789 "
+ );
}
fn test_porfile(name: &str) {
{
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
fn handle_error(error: std::io::Error, ofs: usize) -> std::io::Result<usize> {
- if ofs > 0 {
- Ok(ofs)
- } else {
- Err(error)
- }
+ if ofs > 0 { Ok(ofs) } else { Err(error) }
}
fn write_chunk<W>(mut writer: W, chunk: &[u8]) -> std::io::Result<usize>
use encoding_rs::{UTF_8, WINDOWS_1252};
use indexmap::set::MutableValues;
- use itertools::{zip_eq, Itertools};
+ use itertools::{Itertools, zip_eq};
use crate::{
data::{ByteString, Datum, RawString},
dictionary::Dictionary,
identifier::Identifier,
por::{
- write::{write_case, DictionaryWriter, Precision, TrigesimalFloat, TrigesimalInt},
WriteOptions,
+ write::{DictionaryWriter, Precision, TrigesimalFloat, TrigesimalInt, write_case},
},
variable::{MissingValueRange, MissingValues, VarWidth, Variable},
};
output.sort();
let expected = [
- ("1/4/VAR01/", vec!["1/3/One"]),
- ("1/4/VAR31/", vec!["4/abcd3/One"]),
- ("1/4/VAR41/", vec!["8/abcdefghI/Longer value label"]),
- ("1/4/VAR51/", vec!["9/abcdefghiS/value label for 9-byte value"]),
- ("1/4/VAR61/", vec!["A0/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx10/value label for 300-byte value"]),
- ("2/4/VAR14/VAR22/", vec!["1/3/One", "2/3/Two"]),
+ ("1/4/VAR01/", vec!["1/3/One"]),
+ ("1/4/VAR31/", vec!["4/abcd3/One"]),
+ ("1/4/VAR41/", vec!["8/abcdefghI/Longer value label"]),
+ (
+ "1/4/VAR51/",
+ vec!["9/abcdefghiS/value label for 9-byte value"],
+ ),
+ (
+ "1/4/VAR61/",
+ vec![
+ "A0/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx10/value label for 300-byte value",
+ ],
+ ),
+ ("2/4/VAR14/VAR22/", vec!["1/3/One", "2/3/Two"]),
];
for (actual, (exp_prefix, exp_suffixes)) in zip_eq(output, expected) {
// this program. If not, see <http://www.gnu.org/licenses/>.
use crate::parse_encoding;
-use anyhow::{anyhow, Result};
+use anyhow::{Result, anyhow};
use clap::{Args, ValueEnum};
use encoding_rs::Encoding;
use pspp::{
data::cases_to_output,
output::{
+ Details, Item, Text,
driver::{Config, Driver},
pivot::PivotTable,
- Details, Item, Text,
},
sys::{
- raw::{infer_encoding, Decoder, EncodingReport, Magic, Reader, Record},
Records,
+ raw::{Decoder, EncodingReport, Magic, Reader, Record, infer_encoding},
},
};
use serde::Serialize;
ffi::OsStr,
fmt::{Display, Write as _},
fs::File,
- io::{stdout, BufReader, Write},
+ io::{BufReader, Write, stdout},
path::{Path, PathBuf},
rc::Rc,
sync::Arc,
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
-use anyhow::{anyhow, Result};
+use anyhow::{Result, anyhow};
use clap::{Args, ValueEnum};
use pspp::{
data::cases_to_output,
output::{
+ Details, Item, Text,
driver::{Config, Driver},
pivot::PivotTable,
- Details, Item, Text,
},
por::PortableFile,
};
ffi::OsStr,
fmt::{Display, Write as _},
fs::File,
- io::{stdout, BufReader, Write},
+ io::{BufReader, Write, stdout},
path::{Path, PathBuf},
rc::Rc,
sync::Arc,
output::pivot::{Axis3, Dimension, Group, PivotTable, Value},
sys::{
raw::{
- self, infer_encoding,
+ self, DecodedRecord, RawCases, RawDatum, RawWidth, Reader, infer_encoding,
records::{
Compression, DocumentRecord, EncodingRecord, Extension, FileAttributesRecord,
FileHeader, FloatInfoRecord, IntegerInfoRecord, LongName, LongNamesRecord,
VarDisplayRecord, VariableAttributesRecord, VariableRecord, VariableSetRecord,
VeryLongStringsRecord,
},
- DecodedRecord, RawCases, RawDatum, RawWidth, Reader,
},
serialize_endian,
},
variable::{InvalidRole, MissingValues, MissingValuesError, VarType, VarWidth, Variable},
};
-use anyhow::{anyhow, Error as AnyError};
+use anyhow::{Error as AnyError, anyhow};
use binrw::{BinRead, BinWrite, Endian};
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use encoding_rs::{Encoding, UTF_8};
#[derive(ThisError, Clone, Debug)]
pub enum Error {
/// File creation date is not in the expected format format.
- #[error("File creation date {0} is not in the expected format \"DD MMM YY\" format. Using 01 Jan 1970.")]
+ #[error(
+ "File creation date {0} is not in the expected format \"DD MMM YY\" format. Using 01 Jan 1970."
+ )]
InvalidCreationDate(
/// Date.
String,
),
/// File creation time is not in the expected format.
- #[error("File creation time {0} is not in the expected format \"HH:MM:SS\" format. Using midnight.")]
+ #[error(
+ "File creation time {0} is not in the expected format \"HH:MM:SS\" format. Using midnight."
+ )]
InvalidCreationTime(
/// Time.
String,
/// Variable index {start_index} is a {width} that should be followed by
/// long string continuation records through index {end_index} (inclusive),
/// but index {error_index} is not a continuation.
- #[error("Variable index {start_index} is a {width} that should be followed by long string continuation records through index {end_index} (inclusive), but index {error_index} is not a continuation")]
+ #[error(
+ "Variable index {start_index} is a {width} that should be followed by long string continuation records through index {end_index} (inclusive), but index {error_index} is not a continuation"
+ )]
MissingLongStringContinuation {
/// Width of variable.
width: RawWidth,
MrSetError(#[from] MrSetError),
/// Invalid numeric format for counted value {number} in multiple response set {mr_set}.
- #[error(
- "Invalid numeric format for counted value {number} in multiple response set {mr_set}."
- )]
+ #[error("Invalid numeric format for counted value {number} in multiple response set {mr_set}.")]
InvalidMDGroupCountedValue {
/// Multiple response set name.
mr_set: Identifier,
/// Variable with short name {short_name} listed in very long string record
/// with width {width}, which requires only one segment.
- #[error("Variable with short name {short_name} listed in very long string record with width {width}, which requires only one segment.")]
+ #[error(
+ "Variable with short name {short_name} listed in very long string record with width {width}, which requires only one segment."
+ )]
ShortVeryLongString {
/// Short variable name.
short_name: Identifier,
/// with width {width} requires string segments for {n_segments} dictionary
/// indexes starting at index {index}, but the dictionary only contains
/// {len} indexes.
- #[error("Variable with short name {short_name} listed in very long string record with width {width} requires string segments for {n_segments} dictionary indexes starting at index {index}, but the dictionary only contains {len} indexes.")]
+ #[error(
+ "Variable with short name {short_name} listed in very long string record with width {width} requires string segments for {n_segments} dictionary indexes starting at index {index}, but the dictionary only contains {len} indexes."
+ )]
VeryLongStringOverflow {
/// Short variable name.
short_name: Identifier,
/// Variable with short name {short_name} listed in very long string record
/// with width {width} has segment {index} of width {actual} (expected
/// {expected}).
- #[error("Variable with short name {short_name} listed in very long string record with width {width} has segment {index} of width {actual} (expected {expected}).")]
+ #[error(
+ "Variable with short name {short_name} listed in very long string record with width {width} has segment {index} of width {actual} (expected {expected})."
+ )]
VeryLongStringInvalidSegmentWidth {
/// Variable short name.
short_name: Identifier,
/// File designates string variable {name} (index {index}) as weight
/// variable, but weight variables must be numeric.
- #[error("File designates string variable {name} (index {index}) as weight variable, but weight variables must be numeric.")]
+ #[error(
+ "File designates string variable {name} (index {index}) as weight variable, but weight variables must be numeric."
+ )]
InvalidWeightVar {
/// Variable name.
name: Identifier,
/// Long string missing values record says variable {name} has {count}
/// missing values, but only 1 to 3 missing values are allowed.
- #[error("Long string missing values record says variable {name} has {count} missing values, but only 1 to 3 missing values are allowed.")]
+ #[error(
+ "Long string missing values record says variable {name} has {count} missing values, but only 1 to 3 missing values are allowed."
+ )]
LongStringMissingValueInvalidCount {
/// Variable name.
name: Identifier,
/// Unknown extension record with subtype {subtype} at offset {offset:#x},
/// consisting of {count} {size}-byte units. Please feel free to report
/// this as a bug.
- #[error("Unknown extension record with subtype {subtype} at offset {offset:#x}, consisting of {count} {size}-byte units. Please feel free to report this as a bug.")]
+ #[error(
+ "Unknown extension record with subtype {subtype} at offset {offset:#x}, consisting of {count} {size}-byte units. Please feel free to report this as a bug."
+ )]
UnknownExtensionRecord {
/// Extension record file starting offset.
offset: u64,
#[serde(rename_all = "snake_case")]
pub enum Error {
/// Warning that the system file doesn't indicate its own encoding.
- #[error("This system file does not indicate its own character encoding. For best results, specify an encoding explicitly. Use SYSFILE INFO with ENCODING=\"DETECT\" to analyze the possible encodings.")]
+ #[error(
+ "This system file does not indicate its own character encoding. For best results, specify an encoding explicitly. Use SYSFILE INFO with ENCODING=\"DETECT\" to analyze the possible encodings."
+ )]
NoEncoding,
/// Unknown code page.
endian::{FromBytes, ToBytes},
identifier::{Error as IdError, Identifier},
output::{
- pivot::{Axis3, Dimension, Group, PivotTable, Value},
Details, Item, Text,
+ pivot::{Axis3, Dimension, Group, PivotTable, Value},
},
sys::{
- encoding::{default_encoding, get_encoding, Error as EncodingError},
+ encoding::{Error as EncodingError, default_encoding, get_encoding},
raw::records::{
AttributeWarning, Compression, DocumentRecord, EncodingRecord, Extension,
ExtensionWarning, FileAttributesRecord, FileHeader, FloatInfoRecord, HeaderWarning,
use binrw::Endian;
use encoding_rs::{
- Encoding, BIG5, EUC_JP, EUC_KR, GB18030, IBM866, ISO_2022_JP, ISO_8859_10, ISO_8859_13,
- ISO_8859_14, ISO_8859_16, ISO_8859_2, ISO_8859_3, ISO_8859_4, ISO_8859_5, ISO_8859_6,
- ISO_8859_7, ISO_8859_8, KOI8_R, KOI8_U, MACINTOSH, SHIFT_JIS, UTF_8, WINDOWS_1250,
- WINDOWS_1251, WINDOWS_1252, WINDOWS_1253, WINDOWS_1254, WINDOWS_1255, WINDOWS_1256,
- WINDOWS_1257, WINDOWS_1258, WINDOWS_874,
+ BIG5, EUC_JP, EUC_KR, Encoding, GB18030, IBM866, ISO_2022_JP, ISO_8859_2, ISO_8859_3,
+ ISO_8859_4, ISO_8859_5, ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_10, ISO_8859_13,
+ ISO_8859_14, ISO_8859_16, KOI8_R, KOI8_U, MACINTOSH, SHIFT_JIS, UTF_8, WINDOWS_874,
+ WINDOWS_1250, WINDOWS_1251, WINDOWS_1252, WINDOWS_1253, WINDOWS_1254, WINDOWS_1255,
+ WINDOWS_1256, WINDOWS_1257, WINDOWS_1258,
};
use flate2::bufread::ZlibDecoder;
use indexmap::IndexMap;
cell::RefCell,
collections::VecDeque,
fmt::{Debug, Display, Formatter, Result as FmtResult},
- io::{empty, BufRead, Error as IoError, Read, Seek, SeekFrom},
+ io::{BufRead, Error as IoError, Read, Seek, SeekFrom, empty},
iter::repeat_n,
mem::take,
num::NonZeroU8,
InvalidZsavCompression(u32),
/// Document record has document line count ({n}) greater than the maximum number {max}.
- #[error(
- "Document record has document line count ({n}) greater than the maximum number {max}."
- )]
+ #[error("Document record has document line count ({n}) greater than the maximum number {max}.")]
BadDocumentLength {
/// Number of document lines.
n: usize,
/// Following value label record, found record type {0} instead of expected
/// type 4 for variable index record.
- #[
- error(
- "Following value label record, found record type {0} instead of expected type 4 for variable index record"
- )]
+ #[error(
+ "Following value label record, found record type {0} instead of expected type 4 for variable index record"
+ )]
ExpectedVarIndexRecord(
/// Record type.
u32,
},
/// Unexpected end of file {case_ofs} bytes into a {case_len}-byte case.
- #[error("Unexpected end of file {case_ofs} bytes into case {case_number} with expected length {case_len} bytes.")]
+ #[error(
+ "Unexpected end of file {case_ofs} bytes into case {case_number} with expected length {case_len} bytes."
+ )]
EofInCase {
/// Offset into case in bytes.
case_ofs: u64,
}
}
EitherOrBoth::Left((offset, _)) | EitherOrBoth::Right((offset, _)) => {
- return &a[..offset]
+ return &a[..offset];
}
}
}
format::{DisplayPlain, Format, Type},
identifier::{Error as IdError, Identifier},
sys::{
+ ProductVersion,
raw::{
- read_bytes, read_string, read_vec, Decoder, Error, ErrorDetails, Magic, RawDatum,
- RawWidth, Record, RecordString, UntypedDatum, VarTypes, Warning, WarningDetails,
+ Decoder, Error, ErrorDetails, Magic, RawDatum, RawWidth, Record, RecordString,
+ UntypedDatum, VarTypes, Warning, WarningDetails, read_bytes, read_string, read_vec,
},
- serialize_endian, ProductVersion,
+ serialize_endian,
},
variable::{
Alignment, Attributes, Measure, MissingValueRange, MissingValues, MissingValuesError,
},
};
-use binrw::{binrw, BinRead, BinWrite, Endian, Error as BinError};
+use binrw::{BinRead, BinWrite, Endian, Error as BinError, binrw};
use clap::ValueEnum;
use encoding_rs::Encoding;
use itertools::Itertools;
-use serde::{ser::SerializeTuple, Serialize, Serializer};
+use serde::{Serialize, Serializer, ser::SerializeTuple};
use thiserror::Error as ThisError;
/// Type of compression in a system file.
impl Display for RawFormatDisplayMeaning {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
- let type_ = format_name(self.0 .0 >> 16);
- let w = (self.0 .0 >> 8) & 0xff;
- let d = self.0 .0 & 0xff;
+ let type_ = format_name(self.0.0 >> 16);
+ let w = (self.0.0 >> 8) & 0xff;
+ let d = self.0.0 & 0xff;
write!(f, "{type_}{w}.{d}")
}
}
return Err(Error::new(
Some(offsets),
ErrorDetails::BadMissingValueCode(code),
- ))
+ ));
}
};
use num::{Bounded, Zero};
use ordered_float::OrderedFloat;
use std::{
- collections::{hash_map::Entry, HashMap},
+ collections::{HashMap, hash_map::Entry},
error::Error as StdError,
fmt::{Display, Formatter, Result as FmtResult},
iter::repeat_n,
dictionary::Dictionary,
identifier::Identifier,
output::{
- pivot::{tests::assert_lines_eq, Axis3, Dimension, Group, PivotTable, Value},
Details, Item, Text,
+ pivot::{Axis3, Dimension, Group, PivotTable, Value, tests::assert_lines_eq},
},
sys::{
+ WriteOptions,
cooked::ReadOptions,
- raw::{self, records::Compression, ErrorDetails},
+ raw::{self, ErrorDetails, records::Compression},
sack::sack,
- WriteOptions,
},
variable::{VarWidth, Variable},
};
.open_file("src/crypto/testdata/test-encrypted.sav")
.unwrap_err();
assert!(matches!(
- error.downcast::<raw::Error>().unwrap().details,
+ error
+ .downcast::<raw::Error<ErrorDetails>>()
+ .unwrap()
+ .details,
ErrorDetails::Encrypted
));
}
.write_writer(&dictionary, Cursor::new(Vec::new()))
.unwrap();
for case in [
- ["1", "1", "1", "xyzzyquux", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n"],
- ["1", "2", "1", "8", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"],
- ] {
- cases
- .write_case(case.into_iter().map(|s| Datum::String(s)))
- .unwrap();
- }
+ [
+ "1",
+ "1",
+ "1",
+ "xyzzyquux",
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n",
+ ],
+ [
+ "1",
+ "2",
+ "1",
+ "8",
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ ],
+ ] {
+ cases
+ .write_case(case.into_iter().map(|s| Datum::String(s)))
+ .unwrap();
+ }
let sysfile = cases.finish().unwrap().unwrap().into_inner();
let expected_filename = PathBuf::from(&format!(
"src/sys/testdata/write-string-{compression_string}.expected"
identifier::Identifier,
output::spv::Zeros,
sys::{
+ ProductVersion,
encoding::codepage_from_encoding,
raw::{
+ Magic,
records::{
Compression, FloatInfoRecord, RawFormat, RawHeader, RawIntegerInfoRecord,
RawVariableRecord, RawZHeader, RawZTrailer, ZBlock,
},
- Magic,
},
- ProductVersion,
},
variable::{Alignment, Attributes, Measure, ValueLabels, VarWidth},
};
},
identifier::Identifier,
sys::{
+ ReadOptions, WriteOptions,
raw::{
+ Decoder, VarTypes,
records::{
DocumentRecord, Extension, RawHeader, RawVariableRecord, VariableRecord,
},
- Decoder, VarTypes,
},
write::DictionaryWriter,
- ReadOptions, WriteOptions,
},
variable::{Alignment, Attributes, Measure, MissingValueRange, VarWidth, Variable},
};
.unwrap()
.dictionary;
- assert!(actual
- .variable_sets()
- .iter()
- .eq(expected.variable_sets().iter()),);
+ assert!(
+ actual
+ .variable_sets()
+ .iter()
+ .eq(expected.variable_sets().iter()),
+ );
}
/// Test writing multiple response sets.
use hashbrown::HashMap;
use indexmap::Equivalent;
use num::integer::div_ceil;
-use serde::{ser::SerializeSeq, Serialize};
+use serde::{Serialize, ser::SerializeSeq};
use thiserror::Error as ThisError;
use unicase::UniCase;