Skip to content

Commit

Permalink
rust: implement correct serialization of newtypes
Browse files Browse the repository at this point in the history
  • Loading branch information
timbod7 committed Apr 24, 2023
1 parent 55962cd commit 632701a
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 13 deletions.
32 changes: 31 additions & 1 deletion haskell/compiler/adlc-lib1/ADL/Compiler/Backends/Rust.hs
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,44 @@ genNewType m decl Newtype{n_typeParams=typeParams, n_typeExpr=te} = do
phantomFields <- mapM phantomData phantomTypeParams
rustUse (rustScopedName "serde::Serialize")
rustUse (rustScopedName "serde::Deserialize")
rustUse (rustScopedName "serde::Serializer")
rustUse (rustScopedName "serde::Deserializer")

addDeclaration $ renderCommentForDeclaration decl <> render typeName typeParams typeExprStr phantomFields
where
render :: T.Text -> [Ident] -> T.Text -> [T.Text] -> Code
render name typeParams typeExprStr phantomFields
= ctemplate "#[derive($1)]" [T.intercalate "," (S.toList (stdTraitsFor te))]
= ctemplate "#[derive($1)]" [T.intercalate "," (S.toList traits)]
<> ctemplate "pub struct $1$2($3);"
[name, typeParamsExpr typeParams, T.intercalate ", " (["pub " <> typeExprStr] <> (map ("pub " <>) phantomFields))]
<> cline ""
<> ctemplate "impl$2 Serialize for $1$2" [name, typeParamsExpr typeParams]
<> (if null (typeExprTypeParams te) then mempty else ctemplate " where $1: Serialize" [typeExprStr])
<> cline "{"
<> cline " fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>"
<> cline " where"
<> cline " S: Serializer,"
<> cline " {"
<> cline " self.0.serialize(serializer)"
<> cline " }"
<> cline "}"
<> cline ""
<> ctemplate "impl$1 Deserialize<'de> for $2$3" [typeParamsExpr (["'de"] <>typeParams), name, typeParamsExpr typeParams]
<> (if null (typeExprTypeParams te) then mempty else ctemplate " where $1: Deserialize<'de>" [typeExprStr])
<> cline "{"
<> ctemplate " fn deserialize<D>(deserializer: D) -> Result<$1$2, D::Error>" [name, typeParamsExpr typeParams]
<> cline " where"
<> cline " D: Deserializer<'de>,"
<> cline " {"
<> ctemplate " let v = $1::deserialize(deserializer)?;" [turboize typeExprStr]
<> ctemplate " Ok($1($2))" [name, T.intercalate ", " (["v"] <> map (\_ -> "PhantomData") phantomFields)]
<> cline " }"
<> cline "}"
realTypeParams = S.toList (S.difference (S.fromList typeParams) (typeExprTypeParams te))
phantomTypeParams = S.toList (S.difference (S.fromList typeParams) (typeExprTypeParams te))
traits = S.difference (stdTraitsFor te) (S.fromList ["Serialize", "Deserialize"])
turboize s = let (a,b) = T.breakOn "<" s in if T.null b then a else (a <> "::" <> b) -- hack



serdeRenameAttribute :: FieldDetails -> Ident -> Code
Expand Down
25 changes: 24 additions & 1 deletion haskell/compiler/tests/test14/rs-output/test14/adl/test14.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// @generated from adl module test14

use serde::Deserialize;
use serde::Deserializer;
use serde::Serialize;
use serde::Serializer;

#[derive(Clone,Deserialize,PartialEq,Serialize)]
pub struct Switch {
Expand Down Expand Up @@ -36,5 +38,26 @@ pub enum Unsigned {
Null,
}

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
#[derive(Clone,Eq,Hash,PartialEq)]
pub struct Factory(pub String);

impl Serialize for Factory
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for Factory
{
fn deserialize<D>(deserializer: D) -> Result<Factory, D::Error>
where
D: Deserializer<'de>,
{
let v = String::deserialize(deserializer)?;
Ok(Factory(v))
}
}
257 changes: 246 additions & 11 deletions haskell/compiler/tests/test7/rs-output/test7/adl/test7.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// @generated from adl module test7

use serde::Deserialize;
use serde::Deserializer;
use serde::Serialize;
use serde::Serializer;
use std::marker::PhantomData;

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
Expand All @@ -22,49 +24,282 @@ impl<T> Point<T> {

pub type Int1 = i64;

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
#[derive(Clone,Eq,Hash,PartialEq)]
pub struct Int2(pub i64);

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
impl Serialize for Int2
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for Int2
{
fn deserialize<D>(deserializer: D) -> Result<Int2, D::Error>
where
D: Deserializer<'de>,
{
let v = i64::deserialize(deserializer)?;
Ok(Int2(v))
}
}

#[derive(Clone,Eq,Hash,PartialEq)]
pub struct Int3(pub i64);

impl Serialize for Int3
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for Int3
{
fn deserialize<D>(deserializer: D) -> Result<Int3, D::Error>
where
D: Deserializer<'de>,
{
let v = i64::deserialize(deserializer)?;
Ok(Int3(v))
}
}

pub type Int4 = i64;

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
#[derive(Clone,Eq,Hash,PartialEq)]
pub struct Int5<X>(pub i64, pub PhantomData<X>);

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
impl<X> Serialize for Int5<X>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de, X> Deserialize<'de> for Int5<X>
{
fn deserialize<D>(deserializer: D) -> Result<Int5<X>, D::Error>
where
D: Deserializer<'de>,
{
let v = i64::deserialize(deserializer)?;
Ok(Int5(v, PhantomData))
}
}

#[derive(Clone,Eq,Hash,PartialEq)]
pub struct Int6<X>(pub i64, pub PhantomData<X>);

impl<X> Serialize for Int6<X>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de, X> Deserialize<'de> for Int6<X>
{
fn deserialize<D>(deserializer: D) -> Result<Int6<X>, D::Error>
where
D: Deserializer<'de>,
{
let v = i64::deserialize(deserializer)?;
Ok(Int6(v, PhantomData))
}
}

pub type String1 = String;

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
#[derive(Clone,Eq,Hash,PartialEq)]
pub struct String2(pub String);

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
impl Serialize for String2
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for String2
{
fn deserialize<D>(deserializer: D) -> Result<String2, D::Error>
where
D: Deserializer<'de>,
{
let v = String::deserialize(deserializer)?;
Ok(String2(v))
}
}

#[derive(Clone,Eq,Hash,PartialEq)]
pub struct String3(pub String);

impl Serialize for String3
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for String3
{
fn deserialize<D>(deserializer: D) -> Result<String3, D::Error>
where
D: Deserializer<'de>,
{
let v = String::deserialize(deserializer)?;
Ok(String3(v))
}
}

pub type String4 = String;

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
#[derive(Clone,Eq,Hash,PartialEq)]
pub struct String5<X>(pub String, pub PhantomData<X>);

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
impl<X> Serialize for String5<X>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de, X> Deserialize<'de> for String5<X>
{
fn deserialize<D>(deserializer: D) -> Result<String5<X>, D::Error>
where
D: Deserializer<'de>,
{
let v = String::deserialize(deserializer)?;
Ok(String5(v, PhantomData))
}
}

#[derive(Clone,Eq,Hash,PartialEq)]
pub struct String6<X>(pub String, pub PhantomData<X>);

impl<X> Serialize for String6<X>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de, X> Deserialize<'de> for String6<X>
{
fn deserialize<D>(deserializer: D) -> Result<String6<X>, D::Error>
where
D: Deserializer<'de>,
{
let v = String::deserialize(deserializer)?;
Ok(String6(v, PhantomData))
}
}

pub type IntPoint1 = Point<i64>;

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
#[derive(Clone,Eq,Hash,PartialEq)]
pub struct IntPoint2(pub Point<i64>);

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
impl Serialize for IntPoint2
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for IntPoint2
{
fn deserialize<D>(deserializer: D) -> Result<IntPoint2, D::Error>
where
D: Deserializer<'de>,
{
let v = Point::<i64>::deserialize(deserializer)?;
Ok(IntPoint2(v))
}
}

#[derive(Clone,Eq,Hash,PartialEq)]
pub struct IntPoint3(pub Point<i64>);

impl Serialize for IntPoint3
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for IntPoint3
{
fn deserialize<D>(deserializer: D) -> Result<IntPoint3, D::Error>
where
D: Deserializer<'de>,
{
let v = Point::<i64>::deserialize(deserializer)?;
Ok(IntPoint3(v))
}
}

pub type Point1<X> = Point<X>;

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
#[derive(Clone,Eq,Hash,PartialEq)]
pub struct Point2<X>(pub Point<X>);

impl<X> Serialize for Point2<X>
where Point<X>: Serialize
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}

impl<'de, X> Deserialize<'de> for Point2<X>
where Point<X>: Deserialize<'de>
{
fn deserialize<D>(deserializer: D) -> Result<Point2<X>, D::Error>
where
D: Deserializer<'de>,
{
let v = Point::<X>::deserialize(deserializer)?;
Ok(Point2(v))
}
}

pub type IntPoint1A = IntPoint1;

#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)]
Expand Down

0 comments on commit 632701a

Please sign in to comment.