sui_rpc/proto/
mod.rs

1#![allow(clippy::large_enum_variant)]
2#![allow(clippy::doc_overindented_list_items)]
3
4use google::rpc::bad_request::FieldViolation;
5use sui::rpc::v2beta2::ErrorReason;
6
7pub mod google;
8pub mod sui;
9
10type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
11
12#[derive(Debug)]
13pub struct TryFromProtoError {
14    field_violation: FieldViolation,
15    source: Option<BoxError>,
16}
17
18impl std::fmt::Display for TryFromProtoError {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20        write!(f, "error converting from protobuf: ")?;
21
22        write!(f, "field: {}", self.field_violation.field)?;
23
24        if !self.field_violation.reason.is_empty() {
25            write!(f, " reason: {}", self.field_violation.reason)?;
26        }
27
28        if !self.field_violation.description.is_empty() {
29            write!(f, " description: {}", self.field_violation.description)?;
30        }
31
32        Ok(())
33    }
34}
35
36impl std::error::Error for TryFromProtoError {
37    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
38        self.source.as_deref().map(|s| s as _)
39    }
40}
41
42impl TryFromProtoError {
43    pub fn nested<T: AsRef<str>>(mut self, field: T) -> Self {
44        let field = field.as_ref();
45        self.field_violation = self.field_violation.nested(field);
46        self
47    }
48
49    pub fn nested_at<T: AsRef<str>>(mut self, field: T, index: usize) -> Self {
50        let field = field.as_ref();
51        self.field_violation = self.field_violation.nested_at(field, index);
52        self
53    }
54
55    pub fn missing<T: AsRef<str>>(field: T) -> Self {
56        let field = field.as_ref();
57
58        Self {
59            field_violation: FieldViolation::new(field).with_reason(ErrorReason::FieldMissing),
60            source: None,
61        }
62    }
63
64    pub fn invalid<T: AsRef<str>, E: Into<BoxError>>(field: T, error: E) -> Self {
65        let field = field.as_ref();
66        let error = error.into();
67
68        Self {
69            field_violation: FieldViolation::new(field)
70                .with_reason(ErrorReason::FieldInvalid)
71                .with_description(error.to_string()),
72            source: Some(error),
73        }
74    }
75
76    pub fn field_violation(&self) -> &FieldViolation {
77        &self.field_violation
78    }
79}
80
81//
82// TimeStamp
83//
84
85pub fn timestamp_ms_to_proto(timestamp_ms: u64) -> prost_types::Timestamp {
86    let timestamp = std::time::Duration::from_millis(timestamp_ms);
87    prost_types::Timestamp {
88        seconds: timestamp.as_secs() as i64,
89        nanos: timestamp.subsec_nanos() as i32,
90    }
91}
92
93#[allow(clippy::result_large_err)]
94pub fn proto_to_timestamp_ms(timestamp: prost_types::Timestamp) -> Result<u64, TryFromProtoError> {
95    let seconds = std::time::Duration::from_secs(
96        timestamp
97            .seconds
98            .try_into()
99            .map_err(|e| TryFromProtoError::invalid("seconds", e))?,
100    );
101    let nanos = std::time::Duration::from_nanos(
102        timestamp
103            .nanos
104            .try_into()
105            .map_err(|e| TryFromProtoError::invalid("nanos", e))?,
106    );
107
108    (seconds + nanos)
109        .as_millis()
110        .try_into()
111        .map_err(|e| TryFromProtoError::invalid("seconds + nanos", e))
112}