cargo_lambda_metadata/
lambda.rs

1use serde::{
2    Deserialize, Serialize, Serializer,
3    de::{Deserializer, Error, Visitor},
4};
5use std::{fmt, str::FromStr, time::Duration};
6use strum_macros::{Display, EnumString};
7
8use crate::error::MetadataError;
9
10#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
11pub struct Timeout(u32);
12
13impl Timeout {
14    pub fn new(i: u32) -> Timeout {
15        Timeout(i)
16    }
17
18    pub fn is_zero(&self) -> bool {
19        self.0 == 0
20    }
21
22    pub fn duration(&self) -> Duration {
23        Duration::from_secs(self.0 as u64)
24    }
25}
26
27impl Default for Timeout {
28    fn default() -> Self {
29        Timeout(30)
30    }
31}
32
33impl FromStr for Timeout {
34    type Err = MetadataError;
35
36    fn from_str(t: &str) -> Result<Timeout, Self::Err> {
37        let t = u32::from_str(t).map_err(MetadataError::InvalidTimeout)?;
38
39        Ok(Timeout(t))
40    }
41}
42
43impl From<Timeout> for i32 {
44    fn from(t: Timeout) -> i32 {
45        t.0 as i32
46    }
47}
48
49impl From<&Timeout> for i32 {
50    fn from(t: &Timeout) -> i32 {
51        t.0 as i32
52    }
53}
54
55impl From<i32> for Timeout {
56    fn from(t: i32) -> Timeout {
57        Timeout(t as u32)
58    }
59}
60
61#[derive(Clone, Debug, Eq, PartialEq)]
62pub struct Memory(pub i32);
63
64impl From<Memory> for i32 {
65    fn from(m: Memory) -> i32 {
66        (&m).into()
67    }
68}
69
70impl From<&Memory> for i32 {
71    fn from(m: &Memory) -> i32 {
72        m.0
73    }
74}
75
76impl TryFrom<i32> for Memory {
77    type Error = MetadataError;
78
79    fn try_from(m: i32) -> Result<Memory, Self::Error> {
80        if !(128..=10240).contains(&m) {
81            return Err(MetadataError::InvalidMemory(m));
82        }
83        Ok(Memory(m))
84    }
85}
86
87impl<'de> Deserialize<'de> for Memory {
88    fn deserialize<D>(deserializer: D) -> Result<Memory, D::Error>
89    where
90        D: Deserializer<'de>,
91    {
92        struct MemoryVisitor;
93        impl Visitor<'_> for MemoryVisitor {
94            type Value = Memory;
95
96            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
97                formatter.write_str("an integer that matches Lambda's memory values")
98            }
99
100            fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
101            where
102                E: Error,
103            {
104                Memory::try_from(value as i32).map_err(|e| Error::custom(e.to_string()))
105            }
106
107            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
108            where
109                E: serde::de::Error,
110            {
111                self.visit_i64(value as i64)
112            }
113        }
114
115        deserializer.deserialize_i64(MemoryVisitor)
116    }
117}
118
119impl Serialize for Memory {
120    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
121    where
122        S: Serializer,
123    {
124        serializer.serialize_i32(self.into())
125    }
126}
127
128#[derive(Clone, Debug, Default, Display, EnumString, Eq, PartialEq, Serialize)]
129#[strum(ascii_case_insensitive)]
130pub enum Tracing {
131    Active,
132    #[default]
133    PassThrough,
134}
135
136impl Tracing {
137    pub fn as_str(&self) -> &str {
138        match self {
139            Tracing::Active => "Active",
140            Tracing::PassThrough => "PassThrough",
141        }
142    }
143}
144
145impl TryFrom<String> for Tracing {
146    type Error = MetadataError;
147
148    fn try_from(s: String) -> Result<Tracing, Self::Error> {
149        match s.to_lowercase().as_str() {
150            "active" => Ok(Self::Active),
151            "passthrough" => Ok(Self::PassThrough),
152            _ => Err(MetadataError::InvalidTracing(s)),
153        }
154    }
155}
156
157impl<'de> Deserialize<'de> for Tracing {
158    fn deserialize<D>(deserializer: D) -> Result<Tracing, D::Error>
159    where
160        D: Deserializer<'de>,
161    {
162        struct TracingVisitor;
163        impl Visitor<'_> for TracingVisitor {
164            type Value = Tracing;
165
166            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
167                formatter.write_str(
168                    "a string that matches Lambda's tracing options: `active` or `passthrough`",
169                )
170            }
171
172            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
173            where
174                E: Error,
175            {
176                self.visit_string(v.to_string())
177            }
178
179            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
180            where
181                E: Error,
182            {
183                Tracing::try_from(v).map_err(|e| Error::custom(e.to_string()))
184            }
185        }
186
187        deserializer.deserialize_string(TracingVisitor)
188    }
189}