pub struct KeyFile {
pub account_binding: String,
pub databases: BTreeMap<String, DatabaseKey>,
pub image_dat: Option<ImageDatKey>,
}Fields§
§account_binding: String§databases: BTreeMap<String, DatabaseKey>§image_dat: Option<ImageDatKey>Implementations§
Source§impl KeyFile
impl KeyFile
Sourcepub fn empty(account_binding: impl Into<String>) -> Self
pub fn empty(account_binding: impl Into<String>) -> Self
Examples found in repository?
examples/audit_counts.rs (line 12)
4fn run() -> Result<()> {
5 let mut args = std::env::args().skip(1);
6 let path = args.next().ok_or(ProfileError::InvalidQuery)?;
7 let keys = args.next();
8 let location = ProfileLocation::new(path)?;
9 let (keys, plaintext) = if let Some(path) = keys {
10 (KeyFile::load(path)?, false)
11 } else {
12 (KeyFile::empty(location.account_directory()), true)
13 };
14 let r = ProfileReader::open(
15 location,
16 keys,
17 ReadOptions {
18 stopped_or_consistent_snapshot: true,
19 allow_plaintext: plaintext,
20 ..Default::default()
21 },
22 )?;
23 let mut contacts = 0;
24 let mut avatars = 0;
25 let mut q = ListQuery {
26 limit: Some(200),
27 ..Default::default()
28 };
29 loop {
30 let p = r.contacts(&q)?;
31 for c in &p.items {
32 if r.avatar(&c.username).is_ok() {
33 avatars += 1;
34 }
35 }
36 contacts += p.items.len();
37 q.cursor = p.next_cursor;
38 if q.cursor.is_none() {
39 break;
40 }
41 }
42 let mut threads = 0;
43 let mut q = ListQuery {
44 limit: Some(200),
45 ..Default::default()
46 };
47 loop {
48 let p = r.threads(&q)?;
49 threads += p.items.len();
50 q.cursor = p.next_cursor;
51 if q.cursor.is_none() {
52 break;
53 }
54 }
55 let mut groups = 0;
56 let mut members = 0;
57 let mut q = ListQuery {
58 limit: Some(200),
59 ..Default::default()
60 };
61 loop {
62 let p = r.groups(&q)?;
63 for g in &p.items {
64 let mut mq = ListQuery {
65 limit: Some(200),
66 ..Default::default()
67 };
68 loop {
69 let mp = r.group_members(&g.username, &mq)?;
70 members += mp.items.len();
71 mq.cursor = mp.next_cursor;
72 if mq.cursor.is_none() {
73 break;
74 }
75 }
76 }
77 groups += p.items.len();
78 q.cursor = p.next_cursor;
79 if q.cursor.is_none() {
80 break;
81 }
82 }
83 let mut messages = 0;
84 let mut unresolved = 0;
85 let mut decoded = 0;
86 let mut q = MessageQuery {
87 limit: Some(200),
88 ..Default::default()
89 };
90 loop {
91 let p = r.messages(&q)?;
92 for m in &p.items {
93 unresolved += usize::from(m.peer.is_none());
94 decoded += usize::from(m.content.text.is_some());
95 }
96 messages += p.items.len();
97 q.cursor = p.next_cursor;
98 if q.cursor.is_none() {
99 break;
100 }
101 }
102 println!(
103 "{}",
104 serde_json::json!({"databases":r.inventory().len(),"partial":r.coverage().partial,"contacts":contacts,"threads":threads,"groups":groups,"groupMembers":members,"cachedAvatars":avatars,"messages":messages,"decodedBodies":decoded,"unresolvedMessages":unresolved,"writesPerformed":false})
105 );
106 Ok(())
107}Sourcepub fn load(path: impl AsRef<Path>) -> Result<Self>
pub fn load(path: impl AsRef<Path>) -> Result<Self>
Examples found in repository?
examples/contacts.rs (line 10)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 let args: Vec<_> = std::env::args().skip(1).collect();
6 if args.len() != 3 || args[0] != "--stopped-or-consistent-copy" {
7 return Err("usage: contacts --stopped-or-consistent-copy ACCOUNT_ROOT KEYS_FILE".into());
8 }
9 let location = ProfileLocation::new(&args[1])?;
10 let keys = KeyFile::load(&args[2])?;
11 let reader = ProfileReader::open(
12 location,
13 keys,
14 ReadOptions {
15 stopped_or_consistent_snapshot: true,
16 ..Default::default()
17 },
18 )?;
19 println!(
20 "{} contacts",
21 reader.contacts(&ListQuery::default())?.items.len()
22 );
23 Ok(())
24}More examples
examples/apply_text_fixture.rs (line 10)
4fn run() -> Result<()> {
5 let a = std::env::args().skip(1).collect::<Vec<_>>();
6 if a.len() != 3 {
7 return Err(ProfileError::InvalidQuery);
8 }
9 let location = ProfileLocation::new(&a[0])?;
10 let keys = KeyFile::load(&a[1])?;
11 let input: IncomingText =
12 serde_json::from_slice(&std::fs::read(&a[2])?).map_err(|_| ProfileError::InvalidQuery)?;
13 let options = WriteOptions {
14 exclusive_ownership_confirmed: true,
15 allow_plaintext: false,
16 durable_intent_id: "explicit-disposable-fixture-validation".into(),
17 };
18 let first = apply_incoming_text(&location, &keys, &input, &options)?;
19 let retry = apply_incoming_text(&location, &keys, &input, &options)?;
20 let read = mark_read_messages(
21 &location,
22 &keys,
23 &input.peer,
24 std::slice::from_ref(&first.source_id),
25 &options,
26 )?;
27 let read_retry = mark_read_messages(
28 &location,
29 &keys,
30 &input.peer,
31 std::slice::from_ref(&first.source_id),
32 &options,
33 )?;
34 let reader = ProfileReader::open(
35 location,
36 keys,
37 ReadOptions {
38 stopped_or_consistent_snapshot: true,
39 ..Default::default()
40 },
41 )?;
42 let page = reader.messages(&MessageQuery {
43 chat: Some(input.peer),
44 limit: Some(200),
45 ..Default::default()
46 })?;
47 let found = page
48 .items
49 .iter()
50 .find(|v| v.id == first.source_id)
51 .ok_or(ProfileError::InvalidMetadata)?;
52 let exact = found.content.text.as_deref() == Some(input.content.as_str())
53 && found.source.text.as_deref() == Some(input.source_xml.as_str())
54 && found.server_message_id.as_deref() == Some(input.server_message_id.as_str());
55 if !exact || retry.message_inserted || read_retry.removed_unread_rows != 0 {
56 return Err(ProfileError::InvalidMetadata);
57 }
58 println!(
59 "{}",
60 serde_json::json!({"newTextInserted":first.message_inserted,"retryInsertedDuplicate":retry.message_inserted,"exactBodySourceAndServerIdentity":exact,"removedUnreadRows":read.removed_unread_rows,"readRetryRemovedRows":read_retry.removed_unread_rows,"unreadBefore":read.unread_count_before,"unreadAfter":read.unread_count_after,"crossDatabaseAtomic":first.cross_database_atomic,"networkUsed":false,"officialRuntimeUsed":false})
61 );
62 Ok(())
63}examples/audit_counts.rs (line 10)
4fn run() -> Result<()> {
5 let mut args = std::env::args().skip(1);
6 let path = args.next().ok_or(ProfileError::InvalidQuery)?;
7 let keys = args.next();
8 let location = ProfileLocation::new(path)?;
9 let (keys, plaintext) = if let Some(path) = keys {
10 (KeyFile::load(path)?, false)
11 } else {
12 (KeyFile::empty(location.account_directory()), true)
13 };
14 let r = ProfileReader::open(
15 location,
16 keys,
17 ReadOptions {
18 stopped_or_consistent_snapshot: true,
19 allow_plaintext: plaintext,
20 ..Default::default()
21 },
22 )?;
23 let mut contacts = 0;
24 let mut avatars = 0;
25 let mut q = ListQuery {
26 limit: Some(200),
27 ..Default::default()
28 };
29 loop {
30 let p = r.contacts(&q)?;
31 for c in &p.items {
32 if r.avatar(&c.username).is_ok() {
33 avatars += 1;
34 }
35 }
36 contacts += p.items.len();
37 q.cursor = p.next_cursor;
38 if q.cursor.is_none() {
39 break;
40 }
41 }
42 let mut threads = 0;
43 let mut q = ListQuery {
44 limit: Some(200),
45 ..Default::default()
46 };
47 loop {
48 let p = r.threads(&q)?;
49 threads += p.items.len();
50 q.cursor = p.next_cursor;
51 if q.cursor.is_none() {
52 break;
53 }
54 }
55 let mut groups = 0;
56 let mut members = 0;
57 let mut q = ListQuery {
58 limit: Some(200),
59 ..Default::default()
60 };
61 loop {
62 let p = r.groups(&q)?;
63 for g in &p.items {
64 let mut mq = ListQuery {
65 limit: Some(200),
66 ..Default::default()
67 };
68 loop {
69 let mp = r.group_members(&g.username, &mq)?;
70 members += mp.items.len();
71 mq.cursor = mp.next_cursor;
72 if mq.cursor.is_none() {
73 break;
74 }
75 }
76 }
77 groups += p.items.len();
78 q.cursor = p.next_cursor;
79 if q.cursor.is_none() {
80 break;
81 }
82 }
83 let mut messages = 0;
84 let mut unresolved = 0;
85 let mut decoded = 0;
86 let mut q = MessageQuery {
87 limit: Some(200),
88 ..Default::default()
89 };
90 loop {
91 let p = r.messages(&q)?;
92 for m in &p.items {
93 unresolved += usize::from(m.peer.is_none());
94 decoded += usize::from(m.content.text.is_some());
95 }
96 messages += p.items.len();
97 q.cursor = p.next_cursor;
98 if q.cursor.is_none() {
99 break;
100 }
101 }
102 println!(
103 "{}",
104 serde_json::json!({"databases":r.inventory().len(),"partial":r.coverage().partial,"contacts":contacts,"threads":threads,"groups":groups,"groupMembers":members,"cachedAvatars":avatars,"messages":messages,"decodedBodies":decoded,"unresolvedMessages":unresolved,"writesPerformed":false})
105 );
106 Ok(())
107}pub fn from_json(input: &[u8]) -> Result<Self>
Trait Implementations§
Auto Trait Implementations§
impl Freeze for KeyFile
impl RefUnwindSafe for KeyFile
impl Send for KeyFile
impl Sync for KeyFile
impl Unpin for KeyFile
impl UnsafeUnpin for KeyFile
impl UnwindSafe for KeyFile
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more