Skip to main content

giga_segy_core/
lib.rs

1//! This library is the foundation for the `giga-segy-in` and `giga-segy-out` crates. It can be built either
2//! with serialization support, or in a slightly more lightweight manner without it (see features).
3#![allow(clippy::derive_partial_eq_without_eq)]
4extern crate num;
5#[macro_use]
6extern crate num_derive;
7extern crate ibmfloat;
8
9#[cfg(feature = "serde")]
10extern crate serde;
11#[cfg(feature = "to_json")]
12extern crate serde_json;
13
14pub mod bitconverter;
15pub mod enums;
16pub mod errors;
17pub mod header_structs;
18pub mod settings;
19#[cfg(test)]
20mod tests;
21
22pub use errors::RsgError;
23
24pub use enums::*;
25pub use header_structs::*;
26pub use settings::SegySettings;
27
28pub const TAPE_LABEL_LEN: usize = 128;
29pub const TEXT_HEADER_LEN: usize = 3200;
30pub const BIN_HEADER_LEN: usize = 400;
31pub const TRACE_HEADER_LEN: usize = 240;
32pub const INLINE_BYTE_LOCATION: usize = 188;
33pub const CROSSLINE_BYTE_LOCATION: usize = 192;
34pub const CDPX_BYTE_LOCATION: usize = 180;
35pub const CDPY_BYTE_LOCATION: usize = 184;
36
37/// This structure represents a SEG-Y trace.
38///
39/// The Header is parsed and stored in the structure, the data is stored
40/// in a memory map and referenced here as start and end indices.
41#[derive(Debug, Clone, PartialEq)]
42#[repr(C)]
43#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
44pub struct Trace {
45    /// A parsed trace header which contains the trace metadata.
46    pub(crate) trace_header: TraceHeader,
47    /// Starting byte of the trace on the map.
48    pub(crate) trace_start_byte: usize,
49    /// Length of the trace in bytes on the map.
50    pub(crate) trace_byte_len: usize,
51}
52
53/// This structure contains all of the metadata for opening a SEG-Y file.
54///
55/// Different implementations of [`SegyMetadata`] can then be made, depending on what type `S` is
56/// used for the settings. In general [`SegyMetadata`] is used internally by `giga_segy_input`
57/// and `giga_segy_output`, but may also prove suitable for uses elsewhere.
58pub struct SegyMetadata<S> {
59    pub tape_label: Option<TapeLabel>,
60    pub text_header: String,
61    pub extended_headers: Vec<String>,
62    pub bin_header: BinHeader,
63    pub settings: S,
64}
65
66impl Trace {
67    /// Construct a new "trace" from a [`TraceHeader`] and byte locations in the file or slice
68    /// where the trace data is kept. Thus this function can be used both for input and output
69    /// purposes.
70    /// ```
71    /// use giga_segy_core::{Trace, TraceHeader};
72    /// use giga_segy_out::create_headers::CreateTraceHeader;
73    /// use std::io::Write;
74    ///
75    /// let mut fake_file = vec![];
76    ///
77    /// let data_start = 40_000;
78    /// let data = (0..100i32).flat_map(|x| x.to_be_bytes()).collect::<Vec<_>>();
79    ///
80    /// // Pretend to write data to a file, f, here.
81    /// let written = fake_file.write(&data).unwrap();
82    ///
83    /// let th = TraceHeader::default();
84    /// let tr = Trace::new(th, data_start, written);
85    /// assert_eq!(tr.get_start(), 40_000);
86    /// // NB: Length ignores the length of headers.
87    /// assert_eq!(tr.len(), 100 * 4);
88    /// ```
89    pub fn new(trace_header: TraceHeader, data_start: usize, data_len: usize) -> Self {
90        Trace {
91            trace_header,
92            trace_start_byte: data_start,
93            trace_byte_len: data_len,
94        }
95    }
96
97    /// Get a reference to the trace header.
98    pub fn get_header(&self) -> &TraceHeader {
99        &self.trace_header
100    }
101
102    /// Get the starting byte of the trace data.
103    pub fn get_start(&self) -> usize {
104        self.trace_start_byte
105    }
106
107    /// Get the length of the data in bytes.
108    pub fn len(&self) -> usize {
109        self.trace_byte_len
110    }
111
112    /// Obligatory `is_empty` method.
113    pub fn is_empty(&self) -> bool {
114        self.len() == 0
115    }
116}
117
118impl<S> SegyMetadata<S> {
119    pub fn new(
120        tape_label: Option<TapeLabel>,
121        text_header: String,
122        extended_headers: Vec<String>,
123        bin_header: BinHeader,
124        settings: S,
125    ) -> Self {
126        Self {
127            tape_label,
128            text_header,
129            extended_headers,
130            bin_header,
131            settings,
132        }
133    }
134
135    /// Get the SEG-Y Settings.
136    pub fn get_settings(&self) -> &S {
137        &self.settings
138    }
139
140    /// Get the Binary header.
141    pub fn get_tape_label(&self) -> &Option<TapeLabel> {
142        &self.tape_label
143    }
144
145    /// Get the text header.
146    pub fn get_text_header(&self) -> &str {
147        &self.text_header
148    }
149
150    /// Get the extended headers.
151    pub fn extended_headers_iter(&self) -> std::slice::Iter<'_, String> {
152        self.extended_headers.iter()
153    }
154
155    /// Get the extended headers.
156    pub fn get_extended_headers(&self) -> &[String] {
157        &self.extended_headers
158    }
159
160    /// Get the text header as collection of short substrings. This function
161    /// clones the content of the text header.
162    pub fn get_text_header_lines(&self) -> Vec<String> {
163        self.text_header
164            .chars()
165            .collect::<Vec<char>>()
166            .as_slice()
167            .chunks(80)
168            .map(|c| c.iter().collect::<String>())
169            .collect::<Vec<String>>()
170    }
171
172    /// Get the binary header.
173    pub fn get_bin_header(&self) -> &BinHeader {
174        &self.bin_header
175    }
176
177    /// This function gets the Tape Label in a rust compatible format.
178    pub fn get_readable_tape_label(&self) -> Option<ReadableTapeLabel> {
179        self.tape_label.as_ref().map(|l| l.to_readable())
180    }
181
182    /// This function gets all the fields of [`SegyMetadata`] and discards the instance. Used to get all
183    /// data in an efficient manner.
184    /// NB: The internal mapping is discarded in the process.
185    pub fn deconstruct(self) -> (Option<TapeLabel>, String, Vec<String>, BinHeader, S) {
186        let SegyMetadata {
187            tape_label,
188            text_header,
189            extended_headers,
190            bin_header,
191            settings,
192        } = self;
193        (
194            tape_label,
195            text_header,
196            extended_headers,
197            bin_header,
198            settings,
199        )
200    }
201}