use std::cmp::Ordering;
use serde::Serialize;
use crate::core::ArrayIterator;
use crate::core::Deserializer;
use crate::core::JsonbItemType;
use crate::core::ObjectIterator;
use crate::error::*;
use crate::OwnedJsonb;
#[derive(Debug, Clone, Copy)]
pub struct RawJsonb<'a> {
pub(crate) data: &'a [u8],
}
impl<'a> RawJsonb<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self { data }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn len(&self) -> usize {
self.data.as_ref().len()
}
pub fn to_owned(&self) -> OwnedJsonb {
OwnedJsonb::new(self.data.to_vec())
}
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
let mut buf = Vec::with_capacity(self.len());
let formatter = serde_json::ser::CompactFormatter {};
let mut ser = serde_json::Serializer::with_formatter(&mut buf, formatter);
match self.serialize(&mut ser) {
Ok(_) => String::from_utf8(buf).unwrap(),
Err(_) => {
if self.data.is_empty() {
"null".to_string()
} else {
String::from_utf8_lossy(self.data).to_string()
}
}
}
}
pub fn to_pretty_string(&self) -> String {
let mut buf = Vec::with_capacity(self.len());
let formatter = serde_json::ser::PrettyFormatter::new();
let mut ser = serde_json::Serializer::with_formatter(&mut buf, formatter);
match self.serialize(&mut ser) {
Ok(_) => String::from_utf8(buf).unwrap(),
Err(_) => "null".to_string(),
}
}
}
impl<'a> From<&'a [u8]> for RawJsonb<'a> {
fn from(data: &'a [u8]) -> Self {
Self { data }
}
}
impl AsRef<[u8]> for RawJsonb<'_> {
fn as_ref(&self) -> &[u8] {
self.data
}
}
impl Eq for RawJsonb<'_> {}
impl PartialEq for RawJsonb<'_> {
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(other) == Some(Ordering::Equal)
}
}
#[allow(clippy::non_canonical_partial_ord_impl)]
impl PartialOrd for RawJsonb<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let self_type = self.jsonb_item_type().ok()?;
let other_type = other.jsonb_item_type().ok()?;
if let Some(ord) = self_type.partial_cmp(&other_type) {
return Some(ord);
}
match (self_type, other_type) {
(JsonbItemType::Array(self_len), JsonbItemType::Array(other_len)) => {
let self_array_iter = ArrayIterator::new(*self).ok()?.unwrap();
let mut other_array_iter = ArrayIterator::new(*other).ok()?.unwrap();
for (self_res, other_res) in &mut self_array_iter.zip(&mut other_array_iter) {
let self_item = self_res.ok()?;
let other_item = other_res.ok()?;
let ord = self_item.partial_cmp(&other_item)?;
if ord != Ordering::Equal {
return Some(ord);
}
}
Some(self_len.cmp(&other_len))
}
(JsonbItemType::Object(self_len), JsonbItemType::Object(other_len)) => {
let self_object_iter = ObjectIterator::new(*self).ok()?.unwrap();
let mut other_object_iter = ObjectIterator::new(*other).ok()?.unwrap();
for (self_res, other_res) in &mut self_object_iter.zip(&mut other_object_iter) {
let (self_key, self_val) = self_res.ok()?;
let (other_key, other_val) = other_res.ok()?;
let key_ord = self_key.partial_cmp(other_key)?;
if key_ord != Ordering::Equal {
return Some(key_ord);
}
let val_ord = self_val.partial_cmp(&other_val)?;
if val_ord != Ordering::Equal {
return Some(val_ord);
}
}
Some(self_len.cmp(&other_len))
}
(JsonbItemType::String, JsonbItemType::String) => {
let self_val = self.as_str();
let other_val = other.as_str();
match (self_val, other_val) {
(Ok(Some(self_val)), Ok(Some(other_val))) => self_val.partial_cmp(&other_val),
(_, _) => None,
}
}
(JsonbItemType::Number, JsonbItemType::Number) => {
let self_val = self.as_number();
let other_val = other.as_number();
match (self_val, other_val) {
(Ok(Some(self_val)), Ok(Some(other_val))) => self_val.partial_cmp(&other_val),
(_, _) => None,
}
}
(JsonbItemType::Boolean, JsonbItemType::Boolean) => {
let self_val = self.as_bool();
let other_val = other.as_bool();
match (self_val, other_val) {
(Ok(Some(self_val)), Ok(Some(other_val))) => self_val.partial_cmp(&other_val),
(_, _) => None,
}
}
(JsonbItemType::Extension, JsonbItemType::Extension) => {
let self_val = self.as_extension_value();
let other_val = other.as_extension_value();
match (self_val, other_val) {
(Ok(Some(self_val)), Ok(Some(other_val))) => self_val.partial_cmp(&other_val),
(_, _) => None,
}
}
(_, _) => None,
}
}
}
impl Ord for RawJsonb<'_> {
fn cmp(&self, other: &Self) -> Ordering {
match self.partial_cmp(other) {
Some(ordering) => ordering,
None => Ordering::Equal,
}
}
}
pub fn from_raw_jsonb<'de, T>(raw_jsonb: &'de RawJsonb) -> Result<T>
where
T: serde::de::Deserialize<'de>,
{
let mut deserializer = Deserializer::new(raw_jsonb);
let t = T::deserialize(&mut deserializer)?;
if deserializer.end() {
Ok(t)
} else {
Err(Error::InvalidJsonb)
}
}