1use indexmap::IndexSet;
2use serde::{de::DeserializeOwned, Serialize};
3use warg_crypto::{hash::AnyHash, Decode};
4
5pub mod operator;
6pub mod package;
7mod proto_envelope;
8pub mod registry;
9mod serde_envelope;
10
11pub use proto_envelope::{
12 ProtoEnvelope, ProtoEnvelopeBody, PublishedProtoEnvelope, PublishedProtoEnvelopeBody,
13};
14pub use semver::{Version, VersionReq};
15pub use serde_envelope::SerdeEnvelope;
16
17pub trait Record: Clone + Decode + Send + Sync {
19 fn contents(&self) -> IndexSet<&AnyHash>;
23}
24
25pub trait Validator:
27 std::fmt::Debug + Serialize + DeserializeOwned + Default + Send + Sync
28{
29 type Record: Record;
31
32 type Error: Send;
34
35 fn validate(self, record: &ProtoEnvelope<Self::Record>) -> Result<Self, Self::Error>;
37}
38
39fn prost_to_pbjson_timestamp(timestamp: prost_types::Timestamp) -> pbjson_types::Timestamp {
42 pbjson_types::Timestamp {
43 seconds: timestamp.seconds,
44 nanos: timestamp.nanos,
45 }
46}
47
48fn pbjson_to_prost_timestamp(timestamp: pbjson_types::Timestamp) -> prost_types::Timestamp {
49 prost_types::Timestamp {
50 seconds: timestamp.seconds,
51 nanos: timestamp.nanos,
52 }
53}
54
55mod timestamp {
60 use serde::Deserializer;
61 use serde::{Deserialize, Serializer};
62 use std::time::{Duration, SystemTime, UNIX_EPOCH};
63
64 pub fn serialize<S>(timestamp: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: Serializer,
67 {
68 use serde::ser::Error;
69
70 let duration_since_epoch = match timestamp.duration_since(UNIX_EPOCH) {
71 Ok(duration_since_epoch) => duration_since_epoch,
72 Err(_) => return Err(S::Error::custom("timestamp must be later than UNIX_EPOCH")),
73 };
74
75 serializer.serialize_str(&format!(
76 "{secs}.{nsecs}",
77 secs = duration_since_epoch.as_secs(),
78 nsecs = duration_since_epoch.subsec_nanos()
79 ))
80 }
81
82 pub fn deserialize<'de, D>(deserializer: D) -> Result<SystemTime, D::Error>
83 where
84 D: Deserializer<'de>,
85 {
86 use serde::de::Error;
87
88 let s = String::deserialize(deserializer)?;
89 let (secs, nsecs) = s
90 .split_once('.')
91 .ok_or_else(|| D::Error::custom("timestamp must be in the format <secs>.<nsecs>"))?;
92
93 Ok(SystemTime::UNIX_EPOCH
94 + Duration::new(
95 secs.parse::<u64>().map_err(D::Error::custom)?,
96 nsecs.parse::<u32>().map_err(D::Error::custom)?,
97 ))
98 }
99}