use super::models::Document;
use super::reference::{convert_fields_to_serde_value, convert_value_to_serde_value, DocumentReference};
use super::FirestoreError;
use serde::de::DeserializeOwned;
#[derive(Debug, Clone)]
pub struct DocumentSnapshot<'a> {
pub(crate) id: String,
pub(crate) reference: DocumentReference<'a>,
pub(crate) document: Option<Document>,
pub(crate) read_time: Option<String>,
}
impl<'a> DocumentSnapshot<'a> {
pub fn id(&self) -> &str {
&self.id
}
pub fn reference(&self) -> &DocumentReference<'a> {
&self.reference
}
pub fn exists(&self) -> bool {
self.document.is_some()
}
pub fn create_time(&self) -> Option<&str> {
self.document.as_ref().map(|d| d.create_time.as_str())
}
pub fn update_time(&self) -> Option<&str> {
self.document.as_ref().map(|d| d.update_time.as_str())
}
pub fn read_time(&self) -> Option<&str> {
self.read_time.as_deref()
}
pub fn data<T: DeserializeOwned>(&self) -> Result<Option<T>, FirestoreError> {
if let Some(doc) = &self.document {
let serde_value = convert_fields_to_serde_value(doc.fields.clone())?;
let obj = serde_json::from_value(serde_value)?;
Ok(Some(obj))
} else {
Ok(None)
}
}
pub fn get_field<T: DeserializeOwned>(&self, path: &str) -> Result<Option<T>, FirestoreError> {
if let Some(doc) = &self.document {
if let Some(value) = doc.fields.get(path) {
let serde_value = convert_value_to_serde_value(value.clone())?;
let obj = serde_json::from_value(serde_value)?;
Ok(Some(obj))
} else {
Ok(None)
}
} else {
Ok(None)
}
}
}
#[derive(Debug, Clone)]
pub struct QuerySnapshot<'a> {
pub(crate) documents: Vec<DocumentSnapshot<'a>>,
pub(crate) read_time: Option<String>,
}
impl<'a> QuerySnapshot<'a> {
pub fn documents(&self) -> &Vec<DocumentSnapshot<'a>> {
&self.documents
}
pub fn empty(&self) -> bool {
self.documents.is_empty()
}
pub fn size(&self) -> usize {
self.documents.len()
}
pub fn read_time(&self) -> Option<&str> {
self.read_time.as_deref()
}
pub fn iter(&self) -> std::slice::Iter<'_, DocumentSnapshot<'a>> {
self.documents.iter()
}
}
impl<'a> IntoIterator for &'a QuerySnapshot<'a> {
type Item = &'a DocumentSnapshot<'a>;
type IntoIter = std::slice::Iter<'a, DocumentSnapshot<'a>>;
fn into_iter(self) -> Self::IntoIter {
self.documents.iter()
}
}
#[derive(Debug, Clone)]
pub struct WriteResult {
pub write_time: String,
}