use std::{collections::BTreeMap, fmt, ops::Index};
use indexmap::IndexMap;
use prost::{
DecodeError, Message,
bytes::{Buf, BufMut},
encoding::{self, DecodeContext, WireType},
};
use crate::google::firestore::v1::Value;
#[derive(Clone, Default, PartialEq)]
pub struct Fields(IndexMap<String, Value>);
impl Fields {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(capacity: usize) -> Self {
Self(IndexMap::with_capacity(capacity))
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn get(&self, key: &str) -> Option<&Value> {
self.0.get(key)
}
pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
self.0.get_mut(key)
}
pub fn contains_key(&self, key: &str) -> bool {
self.0.contains_key(key)
}
pub fn insert(&mut self, key: String, value: Value) -> Option<Value> {
self.0.insert(key, value)
}
pub fn remove(&mut self, key: &str) -> Option<Value> {
self.0.shift_remove(key)
}
pub fn push(&mut self, key: String, value: Value) {
self.0.shift_remove(&key);
self.0.insert(key, value);
}
pub fn entry(&mut self, key: String) -> indexmap::map::Entry<'_, String, Value> {
self.0.entry(key)
}
pub fn iter(&self) -> indexmap::map::Iter<'_, String, Value> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> indexmap::map::IterMut<'_, String, Value> {
self.0.iter_mut()
}
pub fn keys(&self) -> indexmap::map::Keys<'_, String, Value> {
self.0.keys()
}
pub fn values(&self) -> indexmap::map::Values<'_, String, Value> {
self.0.values()
}
pub fn values_mut(&mut self) -> indexmap::map::ValuesMut<'_, String, Value> {
self.0.values_mut()
}
pub fn sorted(&self) -> Vec<(&String, &Value)> {
let mut entries: Vec<_> = self.0.iter().collect();
entries.sort_unstable_by(|a, b| a.0.cmp(b.0));
entries
}
pub fn clear(&mut self) {
self.0.clear();
}
}
impl fmt::Debug for Fields {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.0.iter()).finish()
}
}
impl FromIterator<(String, Value)> for Fields {
fn from_iter<I: IntoIterator<Item = (String, Value)>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}
impl<const N: usize> From<[(String, Value); N]> for Fields {
fn from(entries: [(String, Value); N]) -> Self {
entries.into_iter().collect()
}
}
impl Index<&str> for Fields {
type Output = Value;
fn index(&self, key: &str) -> &Value {
&self.0[key]
}
}
impl Extend<(String, Value)> for Fields {
fn extend<I: IntoIterator<Item = (String, Value)>>(&mut self, iter: I) {
self.0.extend(iter);
}
}
impl IntoIterator for Fields {
type Item = (String, Value);
type IntoIter = indexmap::map::IntoIter<String, Value>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a> IntoIterator for &'a Fields {
type Item = (&'a String, &'a Value);
type IntoIter = indexmap::map::Iter<'a, String, Value>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<'a> IntoIterator for &'a mut Fields {
type Item = (&'a String, &'a mut Value);
type IntoIter = indexmap::map::IterMut<'a, String, Value>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter_mut()
}
}
#[derive(Clone, Default, PartialEq, Debug)]
pub struct Document {
pub name: String,
pub fields: Fields,
pub create_time: Option<prost_types::Timestamp>,
pub update_time: Option<prost_types::Timestamp>,
}
#[derive(Clone, Default, PartialEq, Debug)]
pub struct MapValue {
pub fields: Fields,
}
#[derive(Clone, Default, PartialEq, Debug)]
pub struct AggregationResult {
pub aggregate_fields: Fields,
}
fn encode_fields(tag: u32, fields: &Fields, buf: &mut impl BufMut) {
for (key, value) in fields {
encoding::encode_key(tag, WireType::LengthDelimited, buf);
encoding::encode_varint(entry_len(key, value) as u64, buf);
if !key.is_empty() {
encoding::string::encode(1, key, buf);
}
if value.value_type.is_some() {
encoding::message::encode(2, value, buf);
}
}
}
fn entry_len(key: &String, value: &Value) -> usize {
let key = if key.is_empty() {
0
} else {
encoding::string::encoded_len(1, key)
};
let value = if value.value_type.is_some() {
encoding::message::encoded_len(2, value)
} else {
0
};
key + value
}
fn fields_len(tag: u32, fields: &Fields) -> usize {
fields
.iter()
.map(|(key, value)| {
let len = entry_len(key, value);
encoding::key_len(tag) + encoding::encoded_len_varint(len as u64) + len
})
.sum()
}
fn merge_fields(
wire_type: WireType,
fields: &mut Fields,
buf: &mut impl Buf,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
encoding::check_wire_type(WireType::LengthDelimited, wire_type)?;
let mut entry = BTreeMap::new();
encoding::btree_map::merge(
encoding::string::merge,
encoding::message::merge,
&mut entry,
buf,
ctx,
)?;
fields.extend(entry);
Ok(())
}
fn context(message: &'static str, field: &'static str) -> impl Fn(DecodeError) -> DecodeError {
move |mut error| {
error.push(message, field);
error
}
}
impl Message for Document {
fn encode_raw(&self, buf: &mut impl BufMut) {
if !self.name.is_empty() {
encoding::string::encode(1, &self.name, buf);
}
encode_fields(2, &self.fields, buf);
if let Some(time) = &self.create_time {
encoding::message::encode(3, time, buf);
}
if let Some(time) = &self.update_time {
encoding::message::encode(4, time, buf);
}
}
fn merge_field(
&mut self,
tag: u32,
wire_type: WireType,
buf: &mut impl Buf,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
match tag {
1 => encoding::string::merge(wire_type, &mut self.name, buf, ctx)
.map_err(context("Document", "name")),
2 => merge_fields(wire_type, &mut self.fields, buf, ctx)
.map_err(context("Document", "fields")),
3 => encoding::message::merge(
wire_type,
self.create_time.get_or_insert_with(Default::default),
buf,
ctx,
)
.map_err(context("Document", "create_time")),
4 => encoding::message::merge(
wire_type,
self.update_time.get_or_insert_with(Default::default),
buf,
ctx,
)
.map_err(context("Document", "update_time")),
_ => encoding::skip_field(wire_type, tag, buf, ctx),
}
}
fn encoded_len(&self) -> usize {
let name = if self.name.is_empty() {
0
} else {
encoding::string::encoded_len(1, &self.name)
};
name + fields_len(2, &self.fields)
+ self
.create_time
.as_ref()
.map_or(0, |time| encoding::message::encoded_len(3, time))
+ self
.update_time
.as_ref()
.map_or(0, |time| encoding::message::encoded_len(4, time))
}
fn clear(&mut self) {
*self = Self::default();
}
}
impl Message for MapValue {
fn encode_raw(&self, buf: &mut impl BufMut) {
encode_fields(1, &self.fields, buf);
}
fn merge_field(
&mut self,
tag: u32,
wire_type: WireType,
buf: &mut impl Buf,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
match tag {
1 => merge_fields(wire_type, &mut self.fields, buf, ctx)
.map_err(context("MapValue", "fields")),
_ => encoding::skip_field(wire_type, tag, buf, ctx),
}
}
fn encoded_len(&self) -> usize {
fields_len(1, &self.fields)
}
fn clear(&mut self) {
self.fields.clear();
}
}
impl Message for AggregationResult {
fn encode_raw(&self, buf: &mut impl BufMut) {
encode_fields(2, &self.aggregate_fields, buf);
}
fn merge_field(
&mut self,
tag: u32,
wire_type: WireType,
buf: &mut impl Buf,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
match tag {
2 => merge_fields(wire_type, &mut self.aggregate_fields, buf, ctx)
.map_err(context("AggregationResult", "aggregate_fields")),
_ => encoding::skip_field(wire_type, tag, buf, ctx),
}
}
fn encoded_len(&self) -> usize {
fields_len(2, &self.aggregate_fields)
}
fn clear(&mut self) {
self.aggregate_fields.clear();
}
}