darn-dmap 0.2.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/Cargo.lock +20 -20
  2. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/Cargo.toml +2 -1
  3. darn_dmap-0.3.0/PKG-INFO +8 -0
  4. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/pyproject.toml +1 -1
  5. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/lib.rs +30 -8
  6. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/record.rs +46 -0
  7. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/tests.rs +8 -0
  8. darn_dmap-0.2.1/PKG-INFO +0 -60
  9. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/.github/workflows/CI.yml +0 -0
  10. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/README.md +0 -0
  11. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/benches/io_benchmarking.rs +0 -0
  12. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/error.rs +0 -0
  13. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/formats/dmap.rs +0 -0
  14. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/formats/fitacf.rs +0 -0
  15. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/formats/grid.rs +0 -0
  16. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/formats/iqdat.rs +0 -0
  17. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/formats/map.rs +0 -0
  18. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/formats/mod.rs +0 -0
  19. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/formats/rawacf.rs +0 -0
  20. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/formats/snd.rs +0 -0
  21. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/src/types.rs +0 -0
  22. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.fitacf +0 -0
  23. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.fitacf.bz2 +0 -0
  24. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.grid +0 -0
  25. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.grid.bz2 +0 -0
  26. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.iqdat +0 -0
  27. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.iqdat.bz2 +0 -0
  28. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.map +0 -0
  29. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.map.bz2 +0 -0
  30. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.rawacf +0 -0
  31. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.rawacf.bz2 +0 -0
  32. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.snd +0 -0
  33. {darn_dmap-0.2.1 → darn_dmap-0.3.0}/tests/test_files/test.snd.bz2 +0 -0
@@ -80,9 +80,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
80
80
 
81
81
  [[package]]
82
82
  name = "cc"
83
- version = "1.2.29"
83
+ version = "1.2.33"
84
84
  source = "registry+https://github.com/rust-lang/crates.io-index"
85
- checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362"
85
+ checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
86
86
  dependencies = [
87
87
  "shlex",
88
88
  ]
@@ -210,7 +210,7 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
210
210
 
211
211
  [[package]]
212
212
  name = "dmap"
213
- version = "0.2.1"
213
+ version = "0.3.0"
214
214
  dependencies = [
215
215
  "bzip2",
216
216
  "criterion",
@@ -255,9 +255,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
255
255
 
256
256
  [[package]]
257
257
  name = "hashbrown"
258
- version = "0.15.4"
258
+ version = "0.15.5"
259
259
  source = "registry+https://github.com/rust-lang/crates.io-index"
260
- checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
260
+ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
261
261
 
262
262
  [[package]]
263
263
  name = "heck"
@@ -291,7 +291,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
291
291
  checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
292
292
  dependencies = [
293
293
  "equivalent",
294
- "hashbrown 0.15.4",
294
+ "hashbrown 0.15.5",
295
295
  ]
296
296
 
297
297
  [[package]]
@@ -342,9 +342,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
342
342
 
343
343
  [[package]]
344
344
  name = "libc"
345
- version = "0.2.174"
345
+ version = "0.2.175"
346
346
  source = "registry+https://github.com/rust-lang/crates.io-index"
347
- checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
347
+ checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
348
348
 
349
349
  [[package]]
350
350
  name = "log"
@@ -509,9 +509,9 @@ dependencies = [
509
509
 
510
510
  [[package]]
511
511
  name = "proc-macro2"
512
- version = "1.0.95"
512
+ version = "1.0.101"
513
513
  source = "registry+https://github.com/rust-lang/crates.io-index"
514
- checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
514
+ checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
515
515
  dependencies = [
516
516
  "unicode-ident",
517
517
  ]
@@ -597,9 +597,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
597
597
 
598
598
  [[package]]
599
599
  name = "rayon"
600
- version = "1.10.0"
600
+ version = "1.11.0"
601
601
  source = "registry+https://github.com/rust-lang/crates.io-index"
602
- checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
602
+ checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
603
603
  dependencies = [
604
604
  "either",
605
605
  "rayon-core",
@@ -607,9 +607,9 @@ dependencies = [
607
607
 
608
608
  [[package]]
609
609
  name = "rayon-core"
610
- version = "1.12.1"
610
+ version = "1.13.0"
611
611
  source = "registry+https://github.com/rust-lang/crates.io-index"
612
- checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
612
+ checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
613
613
  dependencies = [
614
614
  "crossbeam-deque",
615
615
  "crossbeam-utils",
@@ -652,9 +652,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
652
652
 
653
653
  [[package]]
654
654
  name = "rustversion"
655
- version = "1.0.21"
655
+ version = "1.0.22"
656
656
  source = "registry+https://github.com/rust-lang/crates.io-index"
657
- checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
657
+ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
658
658
 
659
659
  [[package]]
660
660
  name = "ryu"
@@ -693,9 +693,9 @@ dependencies = [
693
693
 
694
694
  [[package]]
695
695
  name = "serde_json"
696
- version = "1.0.140"
696
+ version = "1.0.143"
697
697
  source = "registry+https://github.com/rust-lang/crates.io-index"
698
- checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
698
+ checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
699
699
  dependencies = [
700
700
  "itoa",
701
701
  "memchr",
@@ -711,9 +711,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
711
711
 
712
712
  [[package]]
713
713
  name = "syn"
714
- version = "2.0.104"
714
+ version = "2.0.106"
715
715
  source = "registry+https://github.com/rust-lang/crates.io-index"
716
- checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
716
+ checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
717
717
  dependencies = [
718
718
  "proc-macro2",
719
719
  "quote",
@@ -1,8 +1,9 @@
1
1
  [package]
2
2
  name = "dmap"
3
- version = "0.2.1"
3
+ version = "0.3.0"
4
4
  edition = "2021"
5
5
  rust-version = "1.63.0"
6
+ readme = "README.md"
6
7
 
7
8
  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
9
 
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: darn-dmap
3
+ Version: 0.3.0
4
+ Classifier: Programming Language :: Python
5
+ Classifier: Programming Language :: Rust
6
+ Requires-Dist: numpy<3
7
+ Author: Remington Rohel
8
+ Requires-Python: >=3.8
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "darn-dmap"
7
- version = "0.2.1"
7
+ version = "0.3.0"
8
8
  requires-python = ">=3.8"
9
9
  authors = [
10
10
  { name = "Remington Rohel" }
@@ -163,7 +163,7 @@ read_rust!(dmap);
163
163
  /// Generates two functions: `read_[type]` and `read_[type]_lax`, for strict and lax
164
164
  /// reading, respectively.
165
165
  macro_rules! read_py {
166
- ($name:ident, $py_name:literal, $lax_name:literal, $bytes_name:literal, $lax_bytes_name:literal) => {
166
+ ($name:ident, $py_name:literal, $lax_name:literal, $bytes_name:literal, $lax_bytes_name:literal, $sniff_name:literal) => {
167
167
  paste! {
168
168
  #[doc = "Reads a `" $name:upper "` file, returning a list of dictionaries containing the fields." ]
169
169
  #[pyfunction]
@@ -219,29 +219,42 @@ macro_rules! read_py {
219
219
  result.1,
220
220
  ))
221
221
  }
222
+
223
+ #[doc = "Reads a `" $name:upper "` file, returning the first record." ]
224
+ #[pyfunction]
225
+ #[pyo3(name = $sniff_name)]
226
+ #[pyo3(text_signature = "(infile: str, /)")]
227
+ fn [< sniff_ $name _py >](infile: PathBuf) -> PyResult<IndexMap<String, DmapField>> {
228
+ Ok([< $name:camel Record >]::sniff_file(&infile)
229
+ .map_err(PyErr::from)?
230
+ .inner()
231
+ )
232
+ }
222
233
  }
223
234
  }
224
235
  }
225
236
 
226
- read_py!(iqdat, "read_iqdat", "read_iqdat_lax", "read_iqdat_bytes", "read_iqdat_bytes_lax");
237
+ read_py!(iqdat, "read_iqdat", "read_iqdat_lax", "read_iqdat_bytes", "read_iqdat_bytes_lax", "sniff_iqdat");
227
238
  read_py!(
228
239
  rawacf,
229
240
  "read_rawacf",
230
241
  "read_rawacf_lax",
231
242
  "read_rawacf_bytes",
232
- "read_rawacf_bytes_lax"
243
+ "read_rawacf_bytes_lax",
244
+ "sniff_rawacf"
233
245
  );
234
246
  read_py!(
235
247
  fitacf,
236
248
  "read_fitacf",
237
249
  "read_fitacf_lax",
238
250
  "read_fitacf_bytes",
239
- "read_fitacf_bytes_lax"
251
+ "read_fitacf_bytes_lax",
252
+ "sniff_fitacf"
240
253
  );
241
- read_py!(grid, "read_grid", "read_grid_lax", "read_grid_bytes", "read_grid_bytes_lax");
242
- read_py!(map, "read_map", "read_map_lax", "read_map_bytes", "read_map_bytes_lax");
243
- read_py!(snd, "read_snd", "read_snd_lax", "read_snd_bytes", "read_snd_bytes_lax");
244
- read_py!(dmap, "read_dmap", "read_dmap_lax", "read_dmap_bytes", "read_dmap_bytes_lax");
254
+ read_py!(grid, "read_grid", "read_grid_lax", "read_grid_bytes", "read_grid_bytes_lax", "sniff_grid");
255
+ read_py!(map, "read_map", "read_map_lax", "read_map_bytes", "read_map_bytes_lax", "sniff_map");
256
+ read_py!(snd, "read_snd", "read_snd_lax", "read_snd_bytes", "read_snd_bytes_lax", "sniff_snd");
257
+ read_py!(dmap, "read_dmap", "read_dmap_lax", "read_dmap_bytes", "read_dmap_bytes_lax", "sniff_dmap");
245
258
 
246
259
  /// Checks that a list of dictionaries contains DMAP records, then appends to outfile.
247
260
  ///
@@ -359,5 +372,14 @@ fn dmap(m: &Bound<'_, PyModule>) -> PyResult<()> {
359
372
  m.add_function(wrap_pyfunction!(write_grid_bytes_py, m)?)?;
360
373
  m.add_function(wrap_pyfunction!(write_map_bytes_py, m)?)?;
361
374
 
375
+ // Sniff the first record
376
+ m.add_function(wrap_pyfunction!(sniff_dmap_py, m)?)?;
377
+ m.add_function(wrap_pyfunction!(sniff_iqdat_py, m)?)?;
378
+ m.add_function(wrap_pyfunction!(sniff_rawacf_py, m)?)?;
379
+ m.add_function(wrap_pyfunction!(sniff_fitacf_py, m)?)?;
380
+ m.add_function(wrap_pyfunction!(sniff_snd_py, m)?)?;
381
+ m.add_function(wrap_pyfunction!(sniff_grid_py, m)?)?;
382
+ m.add_function(wrap_pyfunction!(sniff_map_py, m)?)?;
383
+
362
384
  Ok(())
363
385
  }
@@ -18,6 +18,36 @@ pub trait Record<'a>:
18
18
  /// Gets the underlying data of `self`.
19
19
  fn inner(self) -> IndexMap<String, DmapField>;
20
20
 
21
+ /// Reads from `dmap_data` and parses into `Vec<Self>`.
22
+ ///
23
+ /// Returns `DmapError` if `dmap_data` cannot be read or contains invalid data.
24
+ fn read_first_record(mut dmap_data: impl Read) -> Result<Self, DmapError>
25
+ where
26
+ Self: Sized,
27
+ Self: Send,
28
+ {
29
+ let mut buffer = [0; 8]; // record size should be an i32 of the data
30
+ let read_result = dmap_data.read(&mut buffer[..])?;
31
+ if read_result < buffer.len() {
32
+ return Err(DmapError::CorruptStream("Unable to read size of first record"))
33
+ }
34
+
35
+ let rec_size = i32::from_le_bytes(buffer[4..8].try_into().unwrap()) as usize; // advance 4 bytes, skipping the "code" field
36
+ if rec_size <= 0 {
37
+ return Err(DmapError::InvalidRecord(format!(
38
+ "Record 0 starting at byte 0 has non-positive size {} <= 0",
39
+ rec_size
40
+ )));
41
+ }
42
+
43
+ let mut rec = vec![0; rec_size];
44
+ rec[0..8].clone_from_slice(&buffer[..]);
45
+ dmap_data.read_exact(&mut rec[8..])?;
46
+ let first_rec = Self::parse_record(&mut Cursor::new(rec))?;
47
+
48
+ Ok(first_rec)
49
+ }
50
+
21
51
  /// Reads from `dmap_data` and parses into `Vec<Self>`.
22
52
  ///
23
53
  /// Returns `DmapError` if `dmap_data` cannot be read or contains invalid data.
@@ -171,6 +201,22 @@ pub trait Record<'a>:
171
201
  }
172
202
  }
173
203
 
204
+ /// Reads the first record of a DMAP file of type `Self`.
205
+ fn sniff_file(infile: &PathBuf) -> Result<Self, DmapError>
206
+ where
207
+ Self: Sized,
208
+ Self: Send,
209
+ {
210
+ let file = File::open(infile)?;
211
+ match infile.extension() {
212
+ Some(ext) if ext == OsStr::new("bz2") => {
213
+ let compressor = BzDecoder::new(file);
214
+ Self::read_first_record(compressor)
215
+ }
216
+ _ => Self::read_first_record(file),
217
+ }
218
+ }
219
+
174
220
  /// Reads a record from `cursor`.
175
221
  fn parse_record(cursor: &mut Cursor<Vec<u8>>) -> Result<Self, DmapError>
176
222
  where
@@ -92,6 +92,14 @@ macro_rules! make_test {
92
92
  // Clean up tempfile
93
93
  remove_file(&tempfile).expect("Unable to delete tempfile");
94
94
  }
95
+
96
+ #[test]
97
+ fn [< test_ $record_type _sniff >] () {
98
+ let filename: PathBuf = PathBuf::from(format!("tests/test_files/test.{}", stringify!($record_type)));
99
+ let data = [< $record_type:camel Record >]::sniff_file(&filename).expect("Unable to sniff file");
100
+ let all_recs = [< $record_type:camel Record >]::read_file(&filename).expect("Unable to read file");
101
+ assert_eq!(data, all_recs[0])
102
+ }
95
103
  }
96
104
  };
97
105
  }
darn_dmap-0.2.1/PKG-INFO DELETED
@@ -1,60 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: darn-dmap
3
- Version: 0.2.1
4
- Classifier: Programming Language :: Python
5
- Classifier: Programming Language :: Rust
6
- Requires-Dist: numpy<3
7
- Author: Remington Rohel
8
- Requires-Python: >=3.8
9
- Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
10
-
11
- # Dmap
12
-
13
- Rust tools for SuperDARN DMAP file format operations.
14
-
15
- This project exposes both Rust and Python APIs for handling DMAP I/O.
16
- I/O can be conducted either on byte buffers, or directly to/from files.
17
-
18
- The SuperDARN DMAP file formats are all supported (IQDAT, RAWACF, FITACF, GRID, MAP, and SND)
19
- as well as a generic DMAP format that is unaware of any required fields or types
20
- (e.g. char, int32) for any fields.
21
-
22
- ## Developer Guidelines
23
-
24
- ### `src/record.rs`
25
- This file contains the `Record` trait, which defines a set of functions that specific DMAP formats must implement.
26
- For example, `read_file(infile: &PathBuf) -> Result<Vec<Self>, DmapError>` is defined in the `Record` trait, and handles
27
- reading in records from a file at the specified path. This function is generic, in that it doesn't know what type of records
28
- (RAWACF, FITACF, etc.) are expected. Also, since it is a trait function, you can only use it through a struct which implements
29
- the trait. For example, the `FitacfRecord` struct defined in `src/formats/fitacf.rs` implements the `Record` trait, and so
30
- you can call `FitacfRecord::read_file(...)` to read a FITACF file, but you couldn't invoke `Record::read_file(...)`.
31
-
32
- ### `src/types.rs`
33
- This file defines necessary structs and enums for encapsulating basic types (`i8`, `u32`, `String`, etc.) into
34
- objects like `DmapField`, `DmapScalar`, `DmapVec`, etc. that abstract over the supported underlying types.
35
- For instance, when reading scalar from a DMAP file, the underlying data type is inferred from the `type` field in the
36
- scalar's metadata, so it can't be known beforehand. This requires some encapsulating type, `DmapScalar` in this case,
37
- which contains the metadata of the field and has a known size for the stack memory.
38
-
39
- This file defines the `Fields` struct, which is used to hold the names and types of the required and optional
40
- scalar and vector fields for a type of DMAP record (RAWACF, FITACF, etc.).
41
-
42
- This file defines the `DmapType` trait and implements it for supported data types that can be in DMAP records, namely
43
- `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`, `f32`, `f64`, and `String`. The implementation of the trait for
44
- these types only means that other types, e.g. `i128`, cannot be stored in DMAP records.
45
-
46
- Lastly, functions for parsing scalars and vectors from a byte buffer are defined in this file.
47
-
48
- ### `src/formats`
49
- This directory holds the files that define the DMAP record formats: IQDAT, RAWACF, FITACF, GRID, MAP, SND, and the generic DMAP.
50
- If you are defining a new DMAP format, you will need to make a new file in this directory following the structure of the
51
- existing files. Essentially, you define the scalar and vector fields, both required and optional, and the groups of vector
52
- fields which must have identical dimensions, then call a macro to autogenerate the struct code for you.
53
-
54
- ### `tests`
55
- In `tests.rs`, integration tests for reading and writing all file types are present. Small example files
56
- are contained in `tests/test_files`.
57
-
58
- ### `benches/io_benchmarking.rs`
59
- This file contains benchmarking functions for checking the performance of the basic read functions.
60
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes