Skip to content

Commit

Permalink
Identity: use identity_bytes in SpacetimeType (#89)
Browse files Browse the repository at this point in the history
* Identity: use identity_bytes in SpacetimeType

* Use SDK's version of Identity instead

Signed-off-by: John Detter <4099508+jdetter@users.noreply.github.com>

* make CI happy

* make axum happy<

* make axum happy v2

* Identity Codegen Impl C# (#100)

* Changes required for identity generation in csharp

* Clippy fix

* Seems to be working

* Fixes based on Mazdak suggestions

---------

Co-authored-by: Boppy <no-reply@boppygames.gg>
Co-authored-by: Derek Brinkmann <dbrinkmann@citadelstudios.net>

* Fix compile error that somehow got merged in from #100

* Minor changes to allow `Identity` columns and reducer args in the SDK

- `sdk::identity::Identity` must now be `Hash`,
  because declaring a `#[primarykey]` column with type `Identity`
  will cause the SDK to generate code that uses `Identity` as a `HashMap` key.
  This instance was previously not necessary because the key would be `Vec<u8>`,
  but probably should've been included anyway.
- The codegen can just refer to `Identity` without path-qualifying,
  because it already imports the `Identity` type into all files it generates.

* address pheobe's review

* pacify clippy

---------

Signed-off-by: John Detter <4099508+jdetter@users.noreply.github.com>
Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
Co-authored-by: Boppy <no-reply@boppygames.gg>
Co-authored-by: Derek Brinkmann <dbrinkmann@citadelstudios.net>
Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
  • Loading branch information
5 people authored Jul 28, 2023
1 parent 3adf973 commit 899dc4f
Show file tree
Hide file tree
Showing 23 changed files with 248 additions and 284 deletions.
3 changes: 1 addition & 2 deletions crates/bindings/src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ pub fn invoke_connection_func<R: ReducerResult>(

/// Creates a reducer context from the given `sender` and `timestamp`.
fn assemble_context(sender: Buffer, timestamp: u64) -> ReducerContext {
let sender = sender.read_array::<32>();
let sender = Identity { data: sender };
let sender = Identity::from_byte_array(sender.read_array::<32>());

let timestamp = Timestamp::UNIX_EPOCH + Duration::from_micros(timestamp);

Expand Down
124 changes: 69 additions & 55 deletions crates/cli/src/subcommands/generate/csharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ fn ty_fmt<'a>(ctx: &'a GenCtx, ty: &'a AlgebraicType, namespace: &'a str) -> imp
fmt_fn(move |f| match ty {
AlgebraicType::Sum(sum_type) => {
// This better be an option type
if is_option_type(sum_type) {
match &sum_type.variants[0].algebraic_type {
if let Some(inner_ty) = sum_type.as_option() {
match inner_ty {
Builtin(b) => match b {
BuiltinType::Bool
| BuiltinType::I8
Expand All @@ -60,22 +60,29 @@ fn ty_fmt<'a>(ctx: &'a GenCtx, ty: &'a AlgebraicType, namespace: &'a str) -> imp
| BuiltinType::U128
| BuiltinType::F32
| BuiltinType::F64 => {
// This has to be a nullable type
write!(f, "{}?", ty_fmt(ctx, &sum_type.variants[0].algebraic_type, namespace))
// This has to be a nullable type.
write!(f, "{}?", ty_fmt(ctx, inner_ty, namespace))
}
_ => {
write!(f, "{}", ty_fmt(ctx, &sum_type.variants[0].algebraic_type, namespace))
write!(f, "{}", ty_fmt(ctx, inner_ty, namespace))
}
},
_ => {
write!(f, "{}", ty_fmt(ctx, &sum_type.variants[0].algebraic_type, namespace))
write!(f, "{}", ty_fmt(ctx, inner_ty, namespace))
}
}
} else {
unimplemented!()
}
}
AlgebraicType::Product(_) => unimplemented!(),
AlgebraicType::Product(prod) => {
// The only type that is allowed here is the identity type. All other types should fail.
if prod.is_identity() {
write!(f, "SpacetimeDB.Identity")
} else {
unimplemented!()
}
}
AlgebraicType::Builtin(b) => match maybe_primitive(b) {
MaybePrimitive::Primitive(p) => f.write_str(p),
MaybePrimitive::Array(ArrayType { elem_ty }) if **elem_ty == AlgebraicType::U8 => f.write_str("byte[]"),
Expand Down Expand Up @@ -169,10 +176,20 @@ fn convert_type<'a>(
namespace: &'a str,
) -> impl fmt::Display + 'a {
fmt_fn(move |f| match ty {
AlgebraicType::Product(_) => unimplemented!(),
AlgebraicType::Product(product) => {
if product.is_identity() {
write!(
f,
"SpacetimeDB.Identity.From({}.AsProductValue().elements[0].AsBytes())",
value
)
} else {
unimplemented!()
}
}
AlgebraicType::Sum(sum_type) => {
if is_option_type(sum_type) {
match &sum_type.variants[0].algebraic_type {
if let Some(inner_ty) = sum_type.as_option() {
match inner_ty {
Builtin(ty) => match ty {
BuiltinType::Bool
| BuiltinType::I8
Expand All @@ -190,15 +207,15 @@ fn convert_type<'a>(
f,
"{}.AsSumValue().tag == 1 ? null : new {}?({}.AsSumValue().value{})",
value,
ty_fmt(ctx, &sum_type.variants[0].algebraic_type, namespace),
ty_fmt(ctx, inner_ty, namespace),
value,
&convert_type(ctx, vecnest, &sum_type.variants[0].algebraic_type, "", namespace),
&convert_type(ctx, vecnest, inner_ty, "", namespace),
),
_ => fmt::Display::fmt(
&convert_type(
ctx,
vecnest,
&sum_type.variants[0].algebraic_type,
inner_ty,
format_args!("{}.AsSumValue().tag == 1 ? null : {}.AsSumValue().value", value, value),
namespace,
),
Expand All @@ -209,7 +226,7 @@ fn convert_type<'a>(
&convert_type(
ctx,
vecnest,
&sum_type.variants[0].algebraic_type,
inner_ty,
format_args!("{}.AsSumValue().tag == 1 ? null : {}.AsSumValue().value", value, value),
namespace,
),
Expand Down Expand Up @@ -261,24 +278,6 @@ fn csharp_typename(ctx: &GenCtx, typeref: AlgebraicTypeRef) -> &str {
ctx.names[typeref.idx()].as_deref().expect("tuples should have names")
}

fn is_option_type(ty: &SumType) -> bool {
if ty.variants.len() != 2 {
return false;
}

if ty.variants[0].name.clone().expect("Variants should have names!") != "some"
|| ty.variants[1].name.clone().expect("Variants should have names!") != "none"
{
return false;
}

if let AlgebraicType::Product(none_type) = &ty.variants[1].algebraic_type {
none_type.elements.is_empty()
} else {
false
}
}

macro_rules! indent_scope {
($x:ident) => {
let mut $x = $x.indented(1);
Expand Down Expand Up @@ -605,7 +604,7 @@ fn autogen_csharp_product_table_common(
}
}
AlgebraicType::Sum(sum) => {
if is_option_type(sum) {
if sum.as_option().is_some() {
writeln!(output, "[SpacetimeDB.Some]").unwrap();
} else {
unimplemented!()
Expand Down Expand Up @@ -656,7 +655,7 @@ fn autogen_csharp_product_table_common(
output,
"private static Dictionary<{type_name}, {name}> {field_name}_Index = new Dictionary<{type_name}, {name}>(16{comparer});"
)
.unwrap();
.unwrap();
}
writeln!(output).unwrap();
// OnInsert method for updating indexes
Expand Down Expand Up @@ -772,7 +771,7 @@ fn autogen_csharp_product_table_common(
output,
"OnUpdate?.Invoke(({name})oldValue,({name})newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo);"
)
.unwrap();
.unwrap();
}
writeln!(output, "}}").unwrap();
writeln!(output).unwrap();
Expand Down Expand Up @@ -815,15 +814,15 @@ fn autogen_csharp_product_table_common(
output,
"public static void OnRowUpdateEvent(SpacetimeDBClient.TableOp op, object oldValue, object newValue, ClientApi.Event dbEvent)"
)
.unwrap();
.unwrap();
writeln!(output, "{{").unwrap();
{
indent_scope!(output);
writeln!(
output,
"OnRowUpdate?.Invoke(op, ({name})oldValue,({name})newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo);"
)
.unwrap();
.unwrap();
}
writeln!(output, "}}").unwrap();
}
Expand Down Expand Up @@ -877,7 +876,7 @@ fn autogen_csharp_product_value_to_struct(
0,
field_type,
format_args!("productValue.elements[{idx}]"),
namespace
namespace,
)
)
.unwrap();
Expand Down Expand Up @@ -950,12 +949,18 @@ fn autogen_csharp_access_funcs_for_struct(
let csharp_field_name_pascal = field_name.replace("r#", "").to_case(Case::Pascal);

let (field_type, csharp_field_type) = match field_type {
AlgebraicType::Product(_) | AlgebraicType::Ref(_) => {
// TODO: We don't allow filtering on tuples right now, its possible we may consider it for the future.
continue;
AlgebraicType::Product(product) => {
if product.is_identity() {
("Identity".into(), "SpacetimeDB.Identity")
} else {
// TODO: We don't allow filtering on tuples right now,
// it's possible we may consider it for the future.
continue;
}
}
AlgebraicType::Sum(_) => {
// TODO: We don't allow filtering on enums right now, its possible we may consider it for the future.
AlgebraicType::Ref(_) | AlgebraicType::Sum(_) => {
// TODO: We don't allow filtering on enums or tuples right now;
// it's possible we may consider it for the future.
continue;
}
AlgebraicType::Builtin(b) => match maybe_primitive(b) {
Expand Down Expand Up @@ -1012,12 +1017,21 @@ fn autogen_csharp_access_funcs_for_struct(
{
indent_scope!(output);
writeln!(output, "var productValue = entry.Item1.AsProductValue();").unwrap();
writeln!(
output,
"var compareValue = ({})productValue.elements[{}].As{}();",
csharp_field_type, col_i, field_type
)
.unwrap();
if field_type == "Identity" {
writeln!(
output,
"var compareValue = Identity.From(productValue.elements[{}].AsProductValue().elements[0].AsBytes());",
col_i
)
.unwrap();
} else {
writeln!(
output,
"var compareValue = ({})productValue.elements[{}].As{}();",
csharp_field_type, col_i, field_type
)
.unwrap();
}
if csharp_field_type == "byte[]" {
writeln!(
output,
Expand Down Expand Up @@ -1076,7 +1090,7 @@ fn autogen_csharp_access_funcs_for_struct(
output,
"public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, SpacetimeDB.SATS.AlgebraicValue v1, SpacetimeDB.SATS.AlgebraicValue v2)"
)
.unwrap();
.unwrap();
writeln!(output, "{{").unwrap();
{
indent_scope!(output);
Expand All @@ -1096,15 +1110,15 @@ fn autogen_csharp_access_funcs_for_struct(
output,
"return SpacetimeDB.SATS.AlgebraicValue.Compare(t.product.elements[0].algebraicType, primaryColumnValue1, primaryColumnValue2);"
)
.unwrap();
.unwrap();
}
writeln!(output, "}}").unwrap();
} else {
writeln!(
output,
"public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, SpacetimeDB.SATS.AlgebraicValue _v1, SpacetimeDB.SATS.AlgebraicValue _v2)"
)
.unwrap();
.unwrap();
writeln!(output, "{{").unwrap();
{
indent_scope!(output);
Expand Down Expand Up @@ -1180,10 +1194,10 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st

match &arg.algebraic_type {
AlgebraicType::Sum(sum_type) => {
if is_option_type(sum_type) {
json_args.push_str(format!("new SomeWrapper({})", arg_name).as_str());
if sum_type.as_option().is_some() {
json_args.push_str(&format!("new SomeWrapper({})", arg_name));
} else {
json_args.push_str(arg_name.as_str());
json_args.push_str(&arg_name);
}
}
AlgebraicType::Product(_) => {
Expand Down
Loading

0 comments on commit 899dc4f

Please sign in to comment.