use crate::Number;
use std::borrow::Cow;
use std::collections::HashMap;
#[cfg(any(
all(aws_sdk_unstable, feature = "serde-deserialize"),
all(aws_sdk_unstable, feature = "serde-serialize")
))]
use serde;
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(
all(aws_sdk_unstable, feature = "serde-serialize"),
derive(serde::Serialize)
)]
#[cfg_attr(
all(aws_sdk_unstable, feature = "serde-deserialize"),
derive(serde::Deserialize)
)]
#[cfg_attr(
any(
all(aws_sdk_unstable, feature = "serde-deserialize"),
all(aws_sdk_unstable, feature = "serde-serialize")
),
serde(untagged)
)]
pub enum Document {
Object(HashMap<String, Document>),
Array(Vec<Document>),
Number(Number),
String(String),
Bool(bool),
Null,
}
impl Document {
pub fn as_object(&self) -> Option<&HashMap<String, Document>> {
if let Self::Object(object) = self {
Some(object)
} else {
None
}
}
pub fn as_object_mut(&mut self) -> Option<&mut HashMap<String, Document>> {
if let Self::Object(object) = self {
Some(object)
} else {
None
}
}
pub fn as_array(&self) -> Option<&Vec<Document>> {
if let Self::Array(array) = self {
Some(array)
} else {
None
}
}
pub fn as_array_mut(&mut self) -> Option<&mut Vec<Document>> {
if let Self::Array(array) = self {
Some(array)
} else {
None
}
}
pub fn as_number(&self) -> Option<&Number> {
if let Self::Number(number) = self {
Some(number)
} else {
None
}
}
pub fn as_string(&self) -> Option<&str> {
if let Self::String(string) = self {
Some(string)
} else {
None
}
}
pub fn as_bool(&self) -> Option<bool> {
if let Self::Bool(boolean) = self {
Some(*boolean)
} else {
None
}
}
pub fn as_null(&self) -> Option<()> {
if let Self::Null = self {
Some(())
} else {
None
}
}
pub fn is_object(&self) -> bool {
matches!(self, Self::Object(_))
}
pub fn is_array(&self) -> bool {
matches!(self, Self::Array(_))
}
pub fn is_number(&self) -> bool {
matches!(self, Self::Number(_))
}
pub fn is_string(&self) -> bool {
matches!(self, Self::String(_))
}
pub fn is_bool(&self) -> bool {
matches!(self, Self::Bool(_))
}
pub fn is_null(&self) -> bool {
matches!(self, Self::Null)
}
}
impl Default for Document {
fn default() -> Self {
Self::Null
}
}
impl From<bool> for Document {
fn from(value: bool) -> Self {
Document::Bool(value)
}
}
impl<'a> From<&'a str> for Document {
fn from(value: &'a str) -> Self {
Document::String(value.to_string())
}
}
impl<'a> From<Cow<'a, str>> for Document {
fn from(value: Cow<'a, str>) -> Self {
Document::String(value.into_owned())
}
}
impl From<String> for Document {
fn from(value: String) -> Self {
Document::String(value)
}
}
impl From<Vec<Document>> for Document {
fn from(values: Vec<Document>) -> Self {
Document::Array(values)
}
}
impl From<HashMap<String, Document>> for Document {
fn from(values: HashMap<String, Document>) -> Self {
Document::Object(values)
}
}
impl From<u64> for Document {
fn from(value: u64) -> Self {
Document::Number(Number::PosInt(value))
}
}
impl From<i64> for Document {
fn from(value: i64) -> Self {
Document::Number(Number::NegInt(value))
}
}
impl From<i32> for Document {
fn from(value: i32) -> Self {
Document::Number(Number::NegInt(value as i64))
}
}
impl From<f64> for Document {
fn from(value: f64) -> Self {
Document::Number(Number::Float(value))
}
}
impl From<Number> for Document {
fn from(value: Number) -> Self {
Document::Number(value)
}
}
#[cfg(test)]
mod test {
#[test]
#[cfg(all(
aws_sdk_unstable,
feature = "serde-serialize",
feature = "serde-deserialize"
))]
fn serialize_json() {
use crate::Document;
use crate::Number;
use std::collections::HashMap;
let mut map: HashMap<String, Document> = HashMap::new();
map.insert("hello".into(), "world".to_string().into());
map.insert("pos_int".into(), Document::Number(Number::PosInt(1).into()));
map.insert(
"neg_int".into(),
Document::Number(Number::NegInt(-1).into()),
);
map.insert(
"float".into(),
Document::Number(Number::Float(0.1 + 0.2).into()),
);
map.insert("true".into(), true.into());
map.insert("false".into(), false.into());
map.insert(
"array".into(),
vec![
map.clone().into(),
"hello-world".to_string().into(),
true.into(),
false.into(),
]
.into(),
);
map.insert("map".into(), map.clone().into());
map.insert("null".into(), Document::Null);
let obj = Document::Object(map);
let target_file = include_str!("../test_data/serialize_document.json");
let json: Result<serde_json::Value, _> = serde_json::from_str(target_file);
assert_eq!(serde_json::to_value(&obj).unwrap(), json.unwrap());
let doc: Result<Document, _> = serde_json::from_str(target_file);
assert_eq!(obj, doc.unwrap());
}
}