Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 2 additions & 53 deletions crates/sats/src/satn.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
use crate::time_duration::TimeDuration;
use crate::timestamp::Timestamp;
use crate::{
algebraic_value::ser::ValueSerializer,
ser::{self, Serialize},
ProductType, ProductTypeElement,
};
use crate::{i256, u256};
use crate::{ser, ProductType, ProductTypeElement};
use core::fmt;
use core::fmt::Write as _;
use derive_more::{From, Into};

/// An extension trait for [`Serialize`] providing formatting methods.
/// An extension trait for [`Serialize`](ser::Serialize) providing formatting methods.
pub trait Satn: ser::Serialize {
/// Formats the value using the SATN data format into the formatter `f`.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down Expand Up @@ -349,53 +345,6 @@ impl<'a, 'f> ser::Serializer for SatnFormatter<'a, 'f> {
})?;
write!(self, ")")
}

unsafe fn serialize_bsatn(self, ty: &crate::AlgebraicType, bsatn: &[u8]) -> Result<Self::Ok, Self::Error> {
// TODO(Centril): Consider instead deserializing the `bsatn` through a
// deserializer that serializes into `self` directly.

// First convert the BSATN to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_bsatn(ty, bsatn) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
value.serialize(self)
}

unsafe fn serialize_bsatn_in_chunks<'c, I: Clone + Iterator<Item = &'c [u8]>>(
self,
ty: &crate::AlgebraicType,
total_bsatn_len: usize,
bsatn: I,
) -> Result<Self::Ok, Self::Error> {
// TODO(Centril): Unlike above, in this case we must at minimum concatenate `bsatn`
// before we can do the piping mentioned above, but that's better than
// serializing to `AlgebraicValue` first, so consider that.

// First convert the BSATN to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_bsatn_in_chunks(ty, total_bsatn_len, bsatn) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
value.serialize(self)
}

unsafe fn serialize_str_in_chunks<'c, I: Clone + Iterator<Item = &'c [u8]>>(
self,
total_len: usize,
string: I,
) -> Result<Self::Ok, Self::Error> {
// First convert the `string` to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_str_in_chunks(total_len, string) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
// This incurs a very minor cost of branching on `AlgebraicValue::String`.
value.serialize(self)
}
}

/// Defines the SATN formatting for arrays.
Expand Down
46 changes: 38 additions & 8 deletions crates/sats/src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ mod impls;
#[cfg(feature = "serde")]
pub mod serde;

use crate::{algebraic_value::ser::ValueSerializer, bsatn, buffer::BufWriter, AlgebraicType};
use core::fmt;
use ethnum::{i256, u256};
pub use spacetimedb_bindings_macro::Serialize;

/// A data format that can deserialize any data structure supported by SATs.
///
Expand Down Expand Up @@ -128,7 +131,18 @@ pub trait Serializer: Sized {
///
/// - `AlgebraicValue::decode(ty, &mut bsatn).is_ok()`.
/// That is, `bsatn` encodes a valid element of `ty`.
unsafe fn serialize_bsatn(self, ty: &AlgebraicType, bsatn: &[u8]) -> Result<Self::Ok, Self::Error>;
unsafe fn serialize_bsatn(self, ty: &AlgebraicType, bsatn: &[u8]) -> Result<Self::Ok, Self::Error> {
// TODO(Centril): Consider instead deserializing the `bsatn` through a
// deserializer that serializes into `self` directly.

// First convert the BSATN to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_bsatn(ty, bsatn) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
value.serialize(self)
}

/// Serialize the given `bsatn` encoded data of type `ty`.
///
Expand Down Expand Up @@ -160,7 +174,19 @@ pub trait Serializer: Sized {
ty: &AlgebraicType,
total_bsatn_len: usize,
bsatn: I,
) -> Result<Self::Ok, Self::Error>;
) -> Result<Self::Ok, Self::Error> {
// TODO(Centril): Unlike above, in this case we must at minimum concatenate `bsatn`
// before we can do the piping mentioned above, but that's better than
// serializing to `AlgebraicValue` first, so consider that.

// First convert the BSATN to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_bsatn_in_chunks(ty, total_bsatn_len, bsatn) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
value.serialize(self)
}

/// Serialize the given `string`.
///
Expand Down Expand Up @@ -194,14 +220,18 @@ pub trait Serializer: Sized {
self,
total_len: usize,
string: I,
) -> Result<Self::Ok, Self::Error>;
) -> Result<Self::Ok, Self::Error> {
// First convert the `string` to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_str_in_chunks(total_len, string) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
// This incurs a very minor cost of branching on `AlgebraicValue::String`.
value.serialize(self)
}
}

use ethnum::{i256, u256};
pub use spacetimedb_bindings_macro::Serialize;

use crate::{bsatn, buffer::BufWriter, AlgebraicType};

/// A **data structure** that can be serialized into any data format supported by
/// the SpacetimeDB Algebraic Type System.
///
Expand Down
51 changes: 1 addition & 50 deletions crates/sats/src/ser/serde.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use super::Serialize as _;
use crate::{i256, u256};
use crate::{
algebraic_value::ser::ValueSerializer,
ser::{self, Serializer},
serde::{SerdeError, SerdeWrapper},
};
use crate::{i256, u256};
use core::fmt;
use serde::ser as serde;

Expand Down Expand Up @@ -123,53 +121,6 @@ impl<S: serde::Serializer> Serializer for SerdeSerializer<S> {
seq.end().map_err(SerdeError)
}
}

unsafe fn serialize_bsatn(self, ty: &crate::AlgebraicType, bsatn: &[u8]) -> Result<Self::Ok, Self::Error> {
// TODO(Centril): Consider instead deserializing the `bsatn` through a
// deserializer that serializes into `self` directly.

// First convert the BSATN to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_bsatn(ty, bsatn) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
value.serialize(self)
}

unsafe fn serialize_bsatn_in_chunks<'a, I: Clone + Iterator<Item = &'a [u8]>>(
self,
ty: &crate::AlgebraicType,
total_bsatn_len: usize,
bsatn: I,
) -> Result<Self::Ok, Self::Error> {
// TODO(Centril): Unlike above, in this case we must at minimum concatenate `bsatn`
// before we can do the piping mentioned above, but that's better than
// serializing to `AlgebraicValue` first, so consider that.

// First convert the BSATN to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_bsatn_in_chunks(ty, total_bsatn_len, bsatn) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
value.serialize(self)
}

unsafe fn serialize_str_in_chunks<'a, I: Clone + Iterator<Item = &'a [u8]>>(
self,
total_len: usize,
string: I,
) -> Result<Self::Ok, Self::Error> {
// First convert the `string` to an `AlgebraicValue`.
// SAFETY: Forward caller requirements of this method to that we are calling.
let res = unsafe { ValueSerializer.serialize_str_in_chunks(total_len, string) };
let value = res.unwrap_or_else(|x| match x {});

// Then serialize that.
// This incurs a very minor cost of branching on `AlgebraicValue::String`.
value.serialize(self)
}
}

/// Serializes array elements by forwarding to `S: serde::SerializeSeq`.
Expand Down
Loading