Skip to content

Commit 40a0b95

Browse files
committed
JSON compatibility layer in Rust.
1 parent 83ea9e3 commit 40a0b95

File tree

2 files changed

+140
-25
lines changed

2 files changed

+140
-25
lines changed

hugr-core/src/types/serialize.rs

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
use std::sync::Arc;
2+
3+
use ordered_float::OrderedFloat;
4+
15
use super::{FuncValueType, MaybeRV, RowVariable, SumType, TypeBase, TypeBound, TypeEnum};
26

37
use super::custom::CustomType;
48

59
use crate::extension::SignatureError;
610
use crate::extension::prelude::{qb_t, usize_t};
711
use crate::ops::AliasDecl;
12+
use crate::types::type_param::{TypeArgVariable, UpperBound};
13+
use crate::types::{Term, Type};
814

915
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
1016
#[serde(tag = "t")]
@@ -60,3 +66,133 @@ impl<RV: MaybeRV> TryFrom<SerSimpleType> for TypeBase<RV> {
6066
})
6167
}
6268
}
69+
70+
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
71+
#[non_exhaustive]
72+
#[serde(tag = "tp")]
73+
pub(super) enum TypeParamSer {
74+
Type { b: TypeBound },
75+
BoundedNat { bound: UpperBound },
76+
String,
77+
Bytes,
78+
Float,
79+
StaticType,
80+
List { param: Box<Term> },
81+
Tuple { params: Vec<Term> },
82+
}
83+
84+
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
85+
#[non_exhaustive]
86+
#[serde(tag = "tya")]
87+
pub(super) enum TypeArgSer {
88+
Type {
89+
ty: Type,
90+
},
91+
BoundedNat {
92+
n: u64,
93+
},
94+
String {
95+
arg: String,
96+
},
97+
Bytes {
98+
#[serde(with = "base64")]
99+
value: Arc<[u8]>,
100+
},
101+
Float {
102+
value: OrderedFloat<f64>,
103+
},
104+
List {
105+
elems: Vec<Term>,
106+
},
107+
Tuple {
108+
elems: Vec<Term>,
109+
},
110+
Variable {
111+
#[serde(flatten)]
112+
v: TypeArgVariable,
113+
},
114+
}
115+
116+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
117+
#[serde(untagged)]
118+
pub(super) enum TermSer {
119+
TypeArg(TypeArgSer),
120+
TypeParam(TypeParamSer),
121+
}
122+
123+
impl From<Term> for TermSer {
124+
fn from(value: Term) -> Self {
125+
match value {
126+
Term::RuntimeType { b } => TermSer::TypeParam(TypeParamSer::Type { b }),
127+
Term::StaticType => TermSer::TypeParam(TypeParamSer::StaticType),
128+
Term::BoundedNatType { bound } => {
129+
TermSer::TypeParam(TypeParamSer::BoundedNat { bound })
130+
}
131+
Term::StringType => TermSer::TypeParam(TypeParamSer::String),
132+
Term::BytesType => TermSer::TypeParam(TypeParamSer::Bytes),
133+
Term::FloatType => TermSer::TypeParam(TypeParamSer::Float),
134+
Term::ListType { param } => TermSer::TypeParam(TypeParamSer::List {
135+
param: Box::new(*param),
136+
}),
137+
Term::TupleType { params } => TermSer::TypeParam(TypeParamSer::Tuple { params }),
138+
Term::Type { ty } => TermSer::TypeArg(TypeArgSer::Type { ty }),
139+
Term::BoundedNat { n } => TermSer::TypeArg(TypeArgSer::BoundedNat { n }),
140+
Term::String { arg } => TermSer::TypeArg(TypeArgSer::String { arg }),
141+
Term::Bytes { value } => TermSer::TypeArg(TypeArgSer::Bytes { value }),
142+
Term::Float { value } => TermSer::TypeArg(TypeArgSer::Float { value }),
143+
Term::List { elems } => TermSer::TypeArg(TypeArgSer::List { elems }),
144+
Term::Tuple { elems } => TermSer::TypeArg(TypeArgSer::Tuple { elems }),
145+
Term::Variable { v } => TermSer::TypeArg(TypeArgSer::Variable { v }),
146+
}
147+
}
148+
}
149+
150+
impl From<TermSer> for Term {
151+
fn from(value: TermSer) -> Self {
152+
match value {
153+
TermSer::TypeParam(param) => match param {
154+
TypeParamSer::Type { b } => Term::RuntimeType { b },
155+
TypeParamSer::StaticType => Term::StaticType,
156+
TypeParamSer::BoundedNat { bound } => Term::BoundedNatType { bound },
157+
TypeParamSer::String => Term::StringType,
158+
TypeParamSer::Bytes => Term::BytesType,
159+
TypeParamSer::Float => Term::FloatType,
160+
TypeParamSer::List { param } => Term::ListType { param },
161+
TypeParamSer::Tuple { params } => Term::TupleType { params },
162+
},
163+
TermSer::TypeArg(arg) => match arg {
164+
TypeArgSer::Type { ty } => Term::Type { ty },
165+
TypeArgSer::BoundedNat { n } => Term::BoundedNat { n },
166+
TypeArgSer::String { arg } => Term::String { arg },
167+
TypeArgSer::Bytes { value } => Term::Bytes { value },
168+
TypeArgSer::Float { value } => Term::Float { value },
169+
TypeArgSer::List { elems } => Term::List { elems },
170+
TypeArgSer::Tuple { elems } => Term::Tuple { elems },
171+
TypeArgSer::Variable { v } => Term::Variable { v },
172+
},
173+
}
174+
}
175+
}
176+
177+
/// Helper for to serialize and deserialize the byte string in [`TypeArg::Bytes`] via base64.
178+
mod base64 {
179+
use std::sync::Arc;
180+
181+
use base64::Engine as _;
182+
use base64::prelude::BASE64_STANDARD;
183+
use serde::{Deserialize, Serialize};
184+
use serde::{Deserializer, Serializer};
185+
186+
pub fn serialize<S: Serializer>(v: &Arc<[u8]>, s: S) -> Result<S::Ok, S::Error> {
187+
let base64 = BASE64_STANDARD.encode(v);
188+
base64.serialize(s)
189+
}
190+
191+
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Arc<[u8]>, D::Error> {
192+
let base64 = String::deserialize(d)?;
193+
BASE64_STANDARD
194+
.decode(base64.as_bytes())
195+
.map(|v| v.into())
196+
.map_err(serde::de::Error::custom)
197+
}
198+
}

hugr-core/src/types/type_param.rs

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ pub type TypeParam = Term;
6161
Clone, Debug, PartialEq, Eq, Hash, derive_more::Display, serde::Deserialize, serde::Serialize,
6262
)]
6363
#[non_exhaustive]
64-
#[serde(tag = "t")]
64+
#[serde(
65+
from = "crate::types::serialize::TermSer",
66+
into = "crate::types::serialize::TermSer"
67+
)]
6568
pub enum Term {
6669
/// The type of runtime types.
6770
#[display("Type{}", match b {
@@ -124,7 +127,6 @@ pub enum Term {
124127
#[display("bytes")]
125128
Bytes {
126129
/// The value of the literal.
127-
#[serde(with = "base64")]
128130
value: Arc<[u8]>,
129131
},
130132
/// A 64-bit floating point number. Instance of [`Term::FloatType`].
@@ -558,29 +560,6 @@ pub enum TypeArgError {
558560
InvalidValue(TypeArg),
559561
}
560562

561-
/// Helper for to serialize and deserialize the byte string in `TypeArg::Bytes` via base64.
562-
mod base64 {
563-
use std::sync::Arc;
564-
565-
use base64::Engine as _;
566-
use base64::prelude::BASE64_STANDARD;
567-
use serde::{Deserialize, Serialize};
568-
use serde::{Deserializer, Serializer};
569-
570-
pub fn serialize<S: Serializer>(v: &Arc<[u8]>, s: S) -> Result<S::Ok, S::Error> {
571-
let base64 = BASE64_STANDARD.encode(v);
572-
base64.serialize(s)
573-
}
574-
575-
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Arc<[u8]>, D::Error> {
576-
let base64 = String::deserialize(d)?;
577-
BASE64_STANDARD
578-
.decode(base64.as_bytes())
579-
.map(|v| v.into())
580-
.map_err(serde::de::Error::custom)
581-
}
582-
}
583-
584563
#[cfg(test)]
585564
mod test {
586565
use itertools::Itertools;

0 commit comments

Comments
 (0)