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}