1pub(crate) mod arrow_convert;
19pub(crate) mod columnar;
20pub(crate) mod compression;
21pub mod constants;
22pub(crate) mod dictionary;
23pub(crate) mod document;
24pub(crate) mod encoding;
25pub mod error;
26pub(crate) mod header;
27pub(crate) mod info_records;
28pub(crate) mod io_utils;
29pub mod metadata;
30pub mod scanner;
31pub(crate) mod value_labels;
32pub(crate) mod variable;
33
34#[cfg(feature = "python")]
35mod python;
36
37use std::fs::File;
38use std::io::{BufReader, Read, Seek};
39use std::path::Path;
40
41use arrow::record_batch::RecordBatch;
42
43use crate::error::Result;
44use crate::scanner::SavScanner;
45
46pub use crate::constants::{Alignment, Measure};
48pub use crate::metadata::{MissingSpec, MrSet, MrType, SpssMetadata, Value};
49pub use crate::scanner::SavScanner as Scanner;
50
51pub fn read_sav(path: impl AsRef<Path>) -> Result<(RecordBatch, SpssMetadata)> {
57 let mut scanner = scan_sav(path)?;
58 let metadata = scanner.metadata().clone();
59 let batch = scanner.collect_single()?;
60 Ok((batch, metadata))
61}
62
63pub fn read_sav_from_reader<R: Read + Seek>(reader: R) -> Result<(RecordBatch, SpssMetadata)> {
65 let mut scanner = scan_sav_from_reader(reader, usize::MAX)?;
66 let metadata = scanner.metadata().clone();
67 let batch = scanner.collect_single()?;
68 Ok((batch, metadata))
69}
70
71pub fn read_sav_metadata(path: impl AsRef<Path>) -> Result<SpssMetadata> {
76 let file = File::open(path)?;
77 let buf_reader = BufReader::with_capacity(4 * 1024 * 1024, file);
78 let scanner = SavScanner::open(buf_reader, 0)?;
79 Ok(scanner.metadata().clone())
80}
81
82pub fn scan_sav(path: impl AsRef<Path>) -> Result<SavScanner<BufReader<File>>> {
100 let file = File::open(path)?;
101 let buf_reader = BufReader::with_capacity(4 * 1024 * 1024, file);
102 SavScanner::open(buf_reader, 100_000)
103}
104
105pub fn scan_sav_from_reader<R: Read + Seek>(
107 reader: R,
108 batch_size: usize,
109) -> Result<SavScanner<R>> {
110 SavScanner::open(reader, batch_size)
111}