azure_functions/
generic.rs

1//! Module for generic Azure Function bindings.
2use crate::{
3    http::Body,
4    rpc::{typed_data::Data, TypedData},
5};
6use serde_json::from_str;
7use std::borrow::Cow;
8
9/// Represents a value passed to or from a generic binding.
10#[derive(Debug, Clone, PartialEq)]
11pub enum Value {
12    /// No data is present.
13    None,
14    /// The value is a string.
15    String(String),
16    /// The value is a JSON value.
17    Json(serde_json::Value),
18    /// The value is a sequence of bytes.
19    Bytes(Vec<u8>),
20    /// The value is an integer.
21    Integer(i64),
22    /// The value is a double.
23    Double(f64),
24}
25
26impl<'a> Into<Body<'a>> for Value {
27    fn into(self) -> Body<'a> {
28        match self {
29            Value::None => Body::Empty,
30            Value::String(s) => Body::String(Cow::Owned(s)),
31            Value::Json(v) => Body::Json(Cow::Owned(v.to_string())),
32            Value::Bytes(b) => Body::Bytes(Cow::Owned(b)),
33            Value::Integer(i) => Body::String(Cow::Owned(i.to_string())),
34            Value::Double(d) => Body::String(Cow::Owned(d.to_string())),
35        }
36    }
37}
38
39#[doc(hidden)]
40impl From<TypedData> for Value {
41    fn from(data: TypedData) -> Self {
42        match data.data {
43            None => Value::None,
44            Some(Data::String(s)) => Value::String(s),
45            Some(Data::Json(s)) => Value::Json(from_str(&s).unwrap()),
46            Some(Data::Bytes(b)) => Value::Bytes(b),
47            Some(Data::Stream(b)) => Value::Bytes(b),
48            Some(Data::Http(_)) => panic!("generic bindings cannot contain HTTP data"),
49            Some(Data::Int(i)) => Value::Integer(i),
50            Some(Data::Double(d)) => Value::Double(d),
51        }
52    }
53}
54
55#[doc(hidden)]
56impl Into<TypedData> for Value {
57    fn into(self) -> TypedData {
58        match self {
59            Value::None => TypedData { data: None },
60            Value::String(s) => TypedData {
61                data: Some(Data::String(s)),
62            },
63            Value::Json(v) => TypedData {
64                data: Some(Data::Json(v.to_string())),
65            },
66            Value::Bytes(b) => TypedData {
67                data: Some(Data::Bytes(b)),
68            },
69            Value::Integer(i) => TypedData {
70                data: Some(Data::Int(i)),
71            },
72            Value::Double(d) => TypedData {
73                data: Some(Data::Double(d)),
74            },
75        }
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82    use crate::rpc::typed_data::Data;
83    use serde_json::json;
84
85    #[test]
86    fn it_converts_from_no_typed_data() {
87        let value: Value = TypedData { data: None }.into();
88
89        assert_eq!(value, Value::None);
90    }
91
92    #[test]
93    fn it_converts_from_string_typed_data() {
94        let value: Value = TypedData {
95            data: Some(Data::String("hello world".into())),
96        }
97        .into();
98
99        assert_eq!(value, Value::String("hello world".into()));
100    }
101
102    #[test]
103    fn it_converts_from_json_typed_data() {
104        let value: Value = TypedData {
105            data: Some(Data::Json(r#"{ "foo": "bar" }"#.to_string())),
106        }
107        .into();
108
109        assert_eq!(value, Value::Json(json!({ "foo": "bar" })));
110    }
111
112    #[test]
113    fn it_converts_from_bytes_typed_data() {
114        let value: Value = TypedData {
115            data: Some(Data::Bytes(vec![1, 2, 3])),
116        }
117        .into();
118
119        assert_eq!(value, Value::Bytes(vec![1, 2, 3]));
120    }
121
122    #[test]
123    fn it_converts_from_stream_typed_data() {
124        let value: Value = TypedData {
125            data: Some(Data::Stream(vec![1, 2, 3])),
126        }
127        .into();
128
129        assert_eq!(value, Value::Bytes(vec![1, 2, 3]));
130    }
131
132    #[test]
133    fn it_converts_from_integer_typed_data() {
134        let value: Value = TypedData {
135            data: Some(Data::Int(12345)),
136        }
137        .into();
138
139        assert_eq!(value, Value::Integer(12345));
140    }
141
142    #[test]
143    fn it_converts_from_double_typed_data() {
144        let value: Value = TypedData {
145            data: Some(Data::Double(12345.6)),
146        }
147        .into();
148
149        assert_eq!(value, Value::Double(12345.6));
150    }
151
152    #[test]
153    fn it_converts_to_no_typed_data() {
154        let data: TypedData = Value::None.into();
155
156        assert_eq!(data.data, None);
157    }
158
159    #[test]
160    fn it_converts_to_string_typed_data() {
161        let data: TypedData = Value::String("hello world".to_owned()).into();
162
163        assert_eq!(data.data, Some(Data::String("hello world".to_owned())));
164    }
165
166    #[test]
167    fn it_converts_to_json_typed_data() {
168        let data: TypedData = Value::Json(json!({ "foo": "bar"})).into();
169
170        assert_eq!(data.data, Some(Data::Json(r#"{"foo":"bar"}"#.to_string())));
171    }
172
173    #[test]
174    fn it_converts_to_bytes_typed_data() {
175        let data: TypedData = Value::Bytes(vec![1, 2, 3]).into();
176
177        assert_eq!(data.data, Some(Data::Bytes(vec![1, 2, 3])));
178    }
179
180    #[test]
181    fn it_converts_to_integer_typed_data() {
182        let data: TypedData = Value::Integer(12345).into();
183
184        assert_eq!(data.data, Some(Data::Int(12345)));
185    }
186
187    #[test]
188    fn it_converts_to_double_typed_data() {
189        let data: TypedData = Value::Double(12345.6).into();
190
191        assert_eq!(data.data, Some(Data::Double(12345.6)));
192    }
193}