this repo has no description
1use cid::Cid; 2use serde::{Deserialize, Serialize}; 3use std::str::FromStr; 4use crate::sync::firehose::SequencedEvent; 5#[derive(Debug, Serialize, Deserialize)] 6pub struct FrameHeader { 7 pub op: i64, 8 pub t: String, 9} 10#[derive(Debug, Serialize, Deserialize)] 11pub struct CommitFrame { 12 pub seq: i64, 13 pub rebase: bool, 14 #[serde(rename = "tooBig")] 15 pub too_big: bool, 16 pub repo: String, 17 pub commit: Cid, 18 pub rev: String, 19 pub since: Option<String>, 20 #[serde(with = "serde_bytes")] 21 pub blocks: Vec<u8>, 22 pub ops: Vec<RepoOp>, 23 pub blobs: Vec<Cid>, 24 pub time: String, 25 #[serde(rename = "prevData", skip_serializing_if = "Option::is_none")] 26 pub prev_data: Option<Cid>, 27} 28#[derive(Debug, Clone, Serialize, Deserialize)] 29struct JsonRepoOp { 30 action: String, 31 path: String, 32 cid: Option<String>, 33 prev: Option<String>, 34} 35#[derive(Debug, Serialize, Deserialize)] 36pub struct RepoOp { 37 pub action: String, 38 pub path: String, 39 pub cid: Option<Cid>, 40 #[serde(skip_serializing_if = "Option::is_none")] 41 pub prev: Option<Cid>, 42} 43#[derive(Debug, Serialize, Deserialize)] 44pub struct IdentityFrame { 45 pub did: String, 46 #[serde(skip_serializing_if = "Option::is_none")] 47 pub handle: Option<String>, 48 pub seq: i64, 49 pub time: String, 50} 51#[derive(Debug, Serialize, Deserialize)] 52pub struct AccountFrame { 53 pub did: String, 54 pub active: bool, 55 #[serde(skip_serializing_if = "Option::is_none")] 56 pub status: Option<String>, 57 pub seq: i64, 58 pub time: String, 59} 60#[derive(Debug, Serialize, Deserialize)] 61pub struct SyncFrame { 62 pub did: String, 63 pub rev: String, 64 #[serde(with = "serde_bytes")] 65 pub blocks: Vec<u8>, 66 pub seq: i64, 67 pub time: String, 68} 69pub struct CommitFrameBuilder { 70 pub seq: i64, 71 pub did: String, 72 pub commit_cid_str: String, 73 pub prev_cid_str: Option<String>, 74 pub ops_json: serde_json::Value, 75 pub blobs: Vec<String>, 76 pub time: chrono::DateTime<chrono::Utc>, 77} 78impl CommitFrameBuilder { 79 pub fn build(self) -> Result<CommitFrame, &'static str> { 80 let commit_cid = Cid::from_str(&self.commit_cid_str) 81 .map_err(|_| "Invalid commit CID")?; 82 let json_ops: Vec<JsonRepoOp> = serde_json::from_value(self.ops_json) 83 .unwrap_or_else(|_| vec![]); 84 let ops: Vec<RepoOp> = json_ops.into_iter().map(|op| { 85 RepoOp { 86 action: op.action, 87 path: op.path, 88 cid: op.cid.and_then(|s| Cid::from_str(&s).ok()), 89 prev: op.prev.and_then(|s| Cid::from_str(&s).ok()), 90 } 91 }).collect(); 92 let blobs: Vec<Cid> = self.blobs.iter() 93 .filter_map(|s| Cid::from_str(s).ok()) 94 .collect(); 95 let rev = placeholder_rev(); 96 Ok(CommitFrame { 97 seq: self.seq, 98 rebase: false, 99 too_big: false, 100 repo: self.did, 101 commit: commit_cid, 102 rev, 103 since: self.prev_cid_str.as_ref().map(|_| placeholder_rev()), 104 blocks: Vec::new(), 105 ops, 106 blobs, 107 time: format_atproto_time(self.time), 108 prev_data: None, 109 }) 110 } 111} 112fn placeholder_rev() -> String { 113 use jacquard::types::{integer::LimitedU32, string::Tid}; 114 Tid::now(LimitedU32::MIN).to_string() 115} 116fn format_atproto_time(dt: chrono::DateTime<chrono::Utc>) -> String { 117 dt.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string() 118} 119impl TryFrom<SequencedEvent> for CommitFrame { 120 type Error = &'static str; 121 fn try_from(event: SequencedEvent) -> Result<Self, Self::Error> { 122 let builder = CommitFrameBuilder { 123 seq: event.seq, 124 did: event.did, 125 commit_cid_str: event.commit_cid.ok_or("Missing commit_cid in event")?, 126 prev_cid_str: event.prev_cid, 127 ops_json: event.ops.unwrap_or_default(), 128 blobs: event.blobs.unwrap_or_default(), 129 time: event.created_at, 130 }; 131 builder.build() 132 } 133}