imessage_database/util/
bundle_id.rs

1/*!
2 Contains logic for parsing [Apple Bundle IDs](https://developer.apple.com/documentation/appstoreconnectapi/bundle-ids).
3*/
4
5/// Parse an App's Bundle ID out of a Balloon's Bundle ID
6///
7/// For example, a Bundle ID like `com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.SafetyMonitorApp.SafetyMonitorMessages`
8/// should get parsed into `com.apple.SafetyMonitorApp.SafetyMonitorMessages`.
9///
10/// # Example
11///
12/// ```
13/// use imessage_database::util::bundle_id::parse_balloon_bundle_id;
14///
15/// let bundle_id = "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.SafetyMonitorApp.SafetyMonitorMessages";
16/// let parsed = parse_balloon_bundle_id(Some(bundle_id)); // Some("com.apple.SafetyMonitorApp.SafetyMonitorMessages")
17/// ```
18pub fn parse_balloon_bundle_id(bundle_id: Option<&str>) -> Option<&str> {
19    bundle_id.and_then(|id| {
20        let mut parts = id.split(':');
21        let first = parts.next();
22
23        // If there is only one part, use that, otherwise get the third part
24        match parts.next() {
25            None => first,
26            // Will be None if there is no third part
27            Some(_) => parts.next(),
28        }
29    })
30}
31
32#[cfg(test)]
33mod tests {
34    use crate::util::bundle_id::parse_balloon_bundle_id;
35
36    #[test]
37    fn can_get_no_balloon_bundle_id() {
38        assert_eq!(parse_balloon_bundle_id(None), None);
39    }
40
41    #[test]
42    fn can_get_balloon_bundle_id_os() {
43        assert_eq!(
44            parse_balloon_bundle_id(Some("com.apple.Handwriting.HandwritingProvider")),
45            Some("com.apple.Handwriting.HandwritingProvider")
46        );
47    }
48
49    #[test]
50    fn can_get_balloon_bundle_id_url() {
51        assert_eq!(
52            parse_balloon_bundle_id(Some("com.apple.messages.URLBalloonProvider")),
53            Some("com.apple.messages.URLBalloonProvider")
54        );
55    }
56
57    #[test]
58    fn can_get_balloon_bundle_id_apple() {
59        assert_eq!(
60            parse_balloon_bundle_id(Some("com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.PassbookUIService.PeerPaymentMessagesExtension")),
61            Some("com.apple.PassbookUIService.PeerPaymentMessagesExtension")
62        );
63    }
64
65    #[test]
66    fn can_get_balloon_bundle_id_third_party() {
67        assert_eq!(
68            parse_balloon_bundle_id(Some("com.apple.messages.MSMessageExtensionBalloonPlugin:QPU8QS3E62:com.contextoptional.OpenTable.Messages")),
69            Some("com.contextoptional.OpenTable.Messages")
70        );
71    }
72}