1use std::collections::HashSet;
2
3use serde::{Deserialize, Serialize};
4
5use crate::id::ObjectId;
6use crate::types::*;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[repr(u8)]
11pub enum TypeTag {
12 Blob = 0x01,
14 Tree = 0x02,
16 Patch = 0x03,
18 Revision = 0x04,
20 Snapshot = 0x05,
22 Intent = 0x06,
24 Change = 0x07,
26 Conflict = 0x08,
28 Capsule = 0x09,
30 Policy = 0x0A,
32 Workstream = 0x0B,
34 RefLog = 0x0C,
36}
37
38impl TypeTag {
39 pub fn from_u8(v: u8) -> Option<Self> {
41 match v {
42 0x01 => Some(Self::Blob),
43 0x02 => Some(Self::Tree),
44 0x03 => Some(Self::Patch),
45 0x04 => Some(Self::Revision),
46 0x05 => Some(Self::Snapshot),
47 0x06 => Some(Self::Intent),
48 0x07 => Some(Self::Change),
49 0x08 => Some(Self::Conflict),
50 0x09 => Some(Self::Capsule),
51 0x0A => Some(Self::Policy),
52 0x0B => Some(Self::Workstream),
53 0x0C => Some(Self::RefLog),
54 _ => None,
55 }
56 }
57
58 pub fn name(&self) -> &'static str {
60 match self {
61 Self::Blob => "blob",
62 Self::Tree => "tree",
63 Self::Patch => "patch",
64 Self::Revision => "revision",
65 Self::Snapshot => "snapshot",
66 Self::Intent => "intent",
67 Self::Change => "change",
68 Self::Conflict => "conflict",
69 Self::Capsule => "capsule",
70 Self::Policy => "policy",
71 Self::Workstream => "workstream",
72 Self::RefLog => "reflog",
73 }
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub enum Object {
80 Blob(Blob),
82 Tree(Tree),
84 Patch(Patch),
86 Revision(Revision),
88 Snapshot(Snapshot),
90 Intent(Intent),
92 Change(Change),
94 Conflict(Conflict),
96 Capsule(Capsule),
98 Policy(Policy),
100 Workstream(Workstream),
102 RefLog(RefLog),
104}
105
106impl Object {
107 pub fn type_tag(&self) -> TypeTag {
109 match self {
110 Object::Blob(_) => TypeTag::Blob,
111 Object::Tree(_) => TypeTag::Tree,
112 Object::Patch(_) => TypeTag::Patch,
113 Object::Revision(_) => TypeTag::Revision,
114 Object::Snapshot(_) => TypeTag::Snapshot,
115 Object::Intent(_) => TypeTag::Intent,
116 Object::Change(_) => TypeTag::Change,
117 Object::Conflict(_) => TypeTag::Conflict,
118 Object::Capsule(_) => TypeTag::Capsule,
119 Object::Policy(_) => TypeTag::Policy,
120 Object::Workstream(_) => TypeTag::Workstream,
121 Object::RefLog(_) => TypeTag::RefLog,
122 }
123 }
124
125 pub fn dependencies(&self) -> Vec<ObjectId> {
130 let mut deps = HashSet::new();
131
132 match self {
133 Object::Blob(_) | Object::Intent(_) | Object::Policy(_) | Object::Workstream(_) => {}
134 Object::Tree(tree) => {
135 for entry in &tree.entries {
136 deps.insert(entry.object_id);
137 }
138 }
139 Object::Patch(patch) => {
140 if let Some(id) = patch.base_object {
141 deps.insert(id);
142 }
143 if let Some(id) = patch.result_object {
144 deps.insert(id);
145 }
146 }
147 Object::Revision(revision) => {
148 for parent in &revision.parents {
149 deps.insert(*parent);
150 }
151 for patch in &revision.patches {
152 deps.insert(*patch);
153 }
154 if let Some(id) = revision.snapshot_base {
155 deps.insert(id);
156 }
157 if let Some(id) = revision.tree {
158 deps.insert(id);
159 }
160 if let Some(id) = revision.capsule_id {
161 deps.insert(id);
162 }
163 }
164 Object::Snapshot(snapshot) => {
165 deps.insert(snapshot.tree_root);
166 deps.insert(snapshot.revision_id);
167 }
168 Object::Change(change) => {
169 if let Some(id) = change.head_revision {
170 deps.insert(id);
171 }
172 }
173 Object::Conflict(conflict) => {
174 if let Some(id) = conflict.base_revision {
175 deps.insert(id);
176 }
177 deps.insert(conflict.left_revision);
178 deps.insert(conflict.right_revision);
179 for id in &conflict.left_patch_ids {
180 deps.insert(*id);
181 }
182 for id in &conflict.right_patch_ids {
183 deps.insert(*id);
184 }
185 for id in &conflict.resolution_patch_ids {
186 deps.insert(*id);
187 }
188 }
189 Object::Capsule(capsule) => {
190 deps.insert(capsule.revision_id);
191 }
192 Object::RefLog(reflog) => {
193 for entry in &reflog.entries {
194 if let Some(old) = entry.old_target {
195 deps.insert(old);
196 }
197 deps.insert(entry.new_target);
198 }
199 }
200 }
201
202 let mut out: Vec<_> = deps.into_iter().collect();
203 out.sort_by_key(|id| id.to_hex());
204 out
205 }
206
207 pub fn serialize_payload(&self) -> Result<Vec<u8>, crate::CoreError> {
209 crate::proto_conv::serialize_object(self)
210 }
211
212 pub fn deserialize_payload(type_tag: TypeTag, data: &[u8]) -> Result<Self, crate::CoreError> {
214 crate::proto_conv::deserialize_object(type_tag, data)
215 }
216}