1use std::{convert::TryFrom as _, ops::Deref, str::FromStr};
4
5use fmt::{Component, RefString};
6use oid::Oid;
7use serde::{Deserialize, Serialize};
8use thiserror::Error;
9
10pub mod collaboration;
11pub use collaboration::{
12 create, get, info, list, parse_refstr, remove, update, CollaborativeObject, Create, Evaluate,
13 Update, Updated,
14};
15
16pub mod storage;
17pub use storage::{Commit, Objects, Reference, Storage};
18
19#[derive(Debug, Error)]
20pub enum ParseObjectId {
21 #[error(transparent)]
22 Git(#[from] oid::str::ParseOidError),
23}
24
25#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
27#[serde(transparent)]
28pub struct ObjectId(Oid);
29
30impl FromStr for ObjectId {
31 type Err = ParseObjectId;
32
33 fn from_str(s: &str) -> Result<Self, Self::Err> {
34 let oid = Oid::from_str(s)?;
35 Ok(ObjectId(oid))
36 }
37}
38
39impl From<Oid> for ObjectId {
40 fn from(oid: Oid) -> Self {
41 ObjectId(oid)
42 }
43}
44
45impl From<&Oid> for ObjectId {
46 fn from(oid: &Oid) -> Self {
47 (*oid).into()
48 }
49}
50
51#[cfg(feature = "git2")]
52impl From<git2::Oid> for ObjectId {
53 fn from(oid: git2::Oid) -> Self {
54 Oid::from(oid).into()
55 }
56}
57
58#[cfg(feature = "git2")]
59impl From<&git2::Oid> for ObjectId {
60 fn from(oid: &git2::Oid) -> Self {
61 ObjectId(Oid::from(*oid))
62 }
63}
64
65impl Deref for ObjectId {
66 type Target = Oid;
67
68 fn deref(&self) -> &Self::Target {
69 &self.0
70 }
71}
72
73impl std::fmt::Display for ObjectId {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(f, "{}", self.0)
76 }
77}
78
79impl From<&ObjectId> for Component<'_> {
80 fn from(id: &ObjectId) -> Self {
81 let refstr = RefString::from(*id);
82
83 Component::from_refstr(refstr)
84 .expect("collaborative object id's are valid refname components")
85 }
86}
87
88impl From<ObjectId> for RefString {
89 fn from(id: ObjectId) -> Self {
90 RefString::try_from(id.0.to_string())
91 .expect("collaborative object id's are valid ref strings")
92 }
93}
94
95#[cfg(test)]
96#[allow(clippy::unwrap_used)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_serde() {
102 let id = ObjectId::from_str("3ad84420bd882f983c2f9b605e7a68f5bdf95f5c").unwrap();
103
104 assert_eq!(
105 serde_json::to_string(&id).unwrap(),
106 serde_json::to_string(&id.0).unwrap()
107 );
108 }
109}