imessage_database/util/
bundle_id.rs1#[must_use]
19pub fn parse_balloon_bundle_id(bundle_id: Option<&str>) -> Option<&str> {
20 bundle_id.and_then(|id| {
21 let mut parts = id.split(':');
22 let first = parts.next();
23
24 match parts.next() {
26 None => first,
27 Some(_) => parts.next(),
29 }
30 })
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::util::bundle_id::parse_balloon_bundle_id;
36
37 #[test]
38 fn can_get_no_balloon_bundle_id() {
39 assert_eq!(parse_balloon_bundle_id(None), None);
40 }
41
42 #[test]
43 fn can_get_balloon_bundle_id() {
44 let cases = [
45 (
46 "os provider without plugin prefix",
47 "com.apple.Handwriting.HandwritingProvider",
48 "com.apple.Handwriting.HandwritingProvider",
49 ),
50 (
51 "url provider without plugin prefix",
52 "com.apple.messages.URLBalloonProvider",
53 "com.apple.messages.URLBalloonProvider",
54 ),
55 (
56 "apple plugin with placeholder team id",
57 "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.PassbookUIService.PeerPaymentMessagesExtension",
58 "com.apple.PassbookUIService.PeerPaymentMessagesExtension",
59 ),
60 (
61 "third-party plugin with team id",
62 "com.apple.messages.MSMessageExtensionBalloonPlugin:QPU8QS3E62:com.contextoptional.OpenTable.Messages",
63 "com.contextoptional.OpenTable.Messages",
64 ),
65 ];
66 for (label, input, expected) in cases {
67 assert_eq!(
68 parse_balloon_bundle_id(Some(input)),
69 Some(expected),
70 "{label}"
71 );
72 }
73 }
74}