knuckles_parse/records/
connect.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4#[cfg(feature = "python")]
5use pyo3::prelude::*;
6
7#[cfg(feature = "python")]
8use knuckles_macro::pydefault;
9
10/// Represents a CONECT record specifying connectivity between atoms.
11///
12/// CONECT records specify the bonds between atoms that are not implied by
13/// the chemical structure. These are particularly important for hetero-compounds,
14/// metal coordination, and disulfide bonds.
15///
16/// # Fields
17///
18/// - `serial`: Serial number of the first atom in the connectivity
19/// - `connected`: Array of up to 4 connected atom serial numbers
20///
21/// # Example
22///
23/// ```rust
24/// use knuckles_parse::records::connect::ConnectRecord;
25///
26/// let line = "CONECT  413  412  414                                                           ";
27/// let connect = ConnectRecord::from(line);
28///
29/// assert_eq!(connect.serial, 413);
30/// assert_eq!(connect.connected[0], Some(412));
31/// assert_eq!(connect.connected[1], Some(414));
32/// ```
33#[derive(Debug, Clone)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
36#[cfg_attr(feature = "python", pydefault)]
37pub struct ConnectRecord {
38    /// Serial number of the atom for which connectivity is being specified
39    pub serial: u32,
40    /// Array of up to 4 connected atom serial numbers
41    pub connected: [Option<u32>; 4],
42}
43
44impl ConnectRecord {
45    /// Create a new ConnectRecord by parsing a CONECT line.
46    ///
47    /// Parses the atom serial number and up to 4 connected atoms from the
48    /// fixed-width fields in the CONECT record.
49    ///
50    /// # Arguments
51    ///
52    /// * `str` - A CONECT line from a PDB file
53    ///
54    /// # Returns
55    ///
56    /// A new `ConnectRecord` with parsed connectivity information.
57    pub fn new(str: &str) -> ConnectRecord {
58        ConnectRecord {
59            serial: str[6..11].trim().parse::<u32>().unwrap_or_default(),
60            connected: [
61                str[11..16].trim().parse::<u32>().ok(),
62                str[16..21].trim().parse::<u32>().ok(),
63                str[21..26].trim().parse::<u32>().ok(),
64                str[26..31].trim().parse::<u32>().ok(),
65            ],
66        }
67    }
68}
69
70impl From<&str> for ConnectRecord {
71    fn from(str: &str) -> Self {
72        ConnectRecord::new(str)
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn parse_connect_line_test() {
82        const LINE: &str =
83            "CONECT  413  412  414                                                           ";
84        let record = ConnectRecord::new(LINE);
85        assert_eq!(record.serial, 413);
86        assert_eq!(record.connected, [Some(412), Some(414), None, None]);
87    }
88}