crates/fig_proto/src/fig_common.rs (218 lines of code) (raw):

//! Fig.js Protocol Buffers use serde::Serialize; use serde::ser::{ SerializeStruct, SerializeTuple, }; use serde_json::Value; use crate::proto::fig_common::*; // Duration conversion impl From<std::time::Duration> for Duration { fn from(value: std::time::Duration) -> Self { Self { secs: value.as_secs(), nanos: value.subsec_nanos(), } } } impl From<Duration> for std::time::Duration { fn from(value: Duration) -> Self { std::time::Duration::new(value.secs, value.nanos) } } // Context utils impl ShellContext {} impl Serialize for ShellContext { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer, { let mut s = serializer.serialize_struct("ShellContext", 14)?; s.serialize_field("pid", &self.pid)?; s.serialize_field("ttys", &self.ttys)?; s.serialize_field("process_name", &self.process_name)?; s.serialize_field("current_working_directory", &self.current_working_directory)?; s.serialize_field("session_id", &self.session_id)?; s.serialize_field("terminal", &self.terminal)?; s.serialize_field("hostname", &self.hostname)?; s.serialize_field("shell_path", &self.shell_path)?; s.serialize_field("wsl_distro", &self.wsl_distro)?; s.serialize_field("environment_variables", &self.environment_variables)?; s.serialize_field("qterm_version", &self.qterm_version)?; s.serialize_field("preexec", &self.preexec)?; s.serialize_field("osc_lock", &self.osc_lock)?; s.serialize_field("alias", &self.alias)?; s.end() } } impl Serialize for EnvironmentVariable { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer, { let mut s = serializer.serialize_tuple(2)?; s.serialize_element(&self.key)?; s.serialize_element(&self.value)?; s.end() } } // JSON utilities impl From<String> for Json { fn from(s: String) -> Self { Self { value: Some(json::Value::String(s)), } } } impl From<u64> for Json { fn from(n: u64) -> Self { Self { value: Some(json::Value::Number(json::Number { number: Some(json::number::Number::U64(n)), })), } } } impl From<i64> for Json { fn from(n: i64) -> Self { Self { value: Some(json::Value::Number(json::Number { number: Some(json::number::Number::I64(n)), })), } } } impl From<f64> for Json { fn from(n: f64) -> Self { Self { value: Some(json::Value::Number(json::Number { number: Some(json::number::Number::F64(n)), })), } } } impl From<bool> for Json { fn from(b: bool) -> Self { Self { value: Some(json::Value::Bool(b)), } } } impl<T> From<Option<T>> for Json where T: Into<Json>, { fn from(opt: Option<T>) -> Self { match opt { Some(v) => v.into(), None => Self { value: Some(json::Value::Null(())), }, } } } impl<K, V> FromIterator<(K, V)> for Json where K: Into<String>, V: Into<Json>, { fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self { Json { value: Some(json::Value::Object(json::Object { map: iter.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), })), } } } impl<I> FromIterator<I> for Json where I: Into<Json>, { fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self { Json { value: Some(json::Value::Array(json::Array { array: iter.into_iter().map(|i| i.into()).collect(), })), } } } impl From<Value> for Json { fn from(value: Value) -> Self { Self { value: Some(match value { Value::Null => json::Value::Null(()), Value::Bool(b) => json::Value::Bool(b), Value::Number(n) => json::Value::Number(json::Number { number: n .as_i64() .map(json::number::Number::I64) .or_else(|| n.as_u64().map(json::number::Number::U64)) .or_else(|| n.as_f64().map(json::number::Number::F64)), }), Value::String(s) => json::Value::String(s), Value::Array(a) => json::Value::Array(json::Array { array: a.into_iter().map(Json::from).collect(), }), Value::Object(o) => json::Value::Object(json::Object { map: o.into_iter().map(|(k, v)| (k, Json::from(v))).collect(), }), }), } } } impl From<Json> for Value { fn from(json: Json) -> Self { match json.value { Some(json::Value::Null(_)) | None => Value::Null, Some(json::Value::Bool(b)) => b.into(), Some(json::Value::Number(n)) => match n.number { Some(json::number::Number::I64(i)) => i.into(), Some(json::number::Number::U64(u)) => u.into(), Some(json::number::Number::F64(f)) => f.into(), None => Value::Null, }, Some(json::Value::String(s)) => s.into(), Some(json::Value::Array(a)) => Value::Array(a.array.into_iter().map(Value::from).collect()), Some(json::Value::Object(o)) => Value::Object( o.map .into_iter() .map(|(key, value)| (key, Value::from(value))) .collect(), ), } } } #[cfg(test)] mod tests { use serde_json::json; use super::*; #[test] fn into_value() { let type_hint_value = |x: Value| x; let type_hint_json = |x: Json| x; assert_eq!(type_hint_value(Json { value: None }.into()), json! {null}); assert_eq!( type_hint_value( Json { value: Some(json::Value::String("hello".into())) } .into() ), json! {"hello"} ); assert_eq!( type_hint_value( Json::from_iter([ ("null".to_string(), type_hint_json(None::<bool>.into())), ("bool".to_string(), type_hint_json(true.into())), ("i64".to_string(), type_hint_json((-123_i64).into())), ("u64".to_string(), type_hint_json(123_u64.into())), ("f64".to_string(), type_hint_json(1.2_f64.into())), ("string".to_string(), type_hint_json("value".to_string().into())), ( "array".to_string(), Json::from_iter(["foo".to_string(), "bar".to_string(), "baz".to_string()]) ), ]) .into() ), json! {{"null": null, "bool": true, "i64": -123, "u64": 123, "f64": 1.2, "string": "value", "array": ["foo", "bar", "baz"]}} ); } }