Skip to main content

arcis_interface/
json.rs

1use crate::types::{CircuitInterface, ScalarKind, Value};
2use serde::{
3    de::{self, MapAccess, Visitor},
4    Deserialize,
5    Deserializer,
6    Serialize,
7};
8use serde_json::{json, Value as JsonValue};
9use std::fmt;
10
11#[derive(Serialize, Deserialize, Debug)]
12pub struct ManticoreInterface {
13    pub inputs: Vec<String>,
14    pub outputs: Vec<String>,
15}
16
17impl ManticoreInterface {
18    pub fn new(inputs: Vec<String>, outputs: Vec<String>) -> Self {
19        Self { inputs, outputs }
20    }
21
22    pub fn serialize(&self) -> Result<String, serde_json::Error> {
23        serde_json::to_string(self)
24    }
25
26    pub fn from_json(input: &str) -> Result<Self, serde_json::Error> {
27        serde_json::from_str(input)
28    }
29}
30
31impl<'de> Deserialize<'de> for CircuitInterface {
32    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33    where
34        D: Deserializer<'de>,
35    {
36        enum Field {
37            Name,
38            Inputs,
39            Outputs,
40        }
41
42        impl<'de> Deserialize<'de> for Field {
43            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
44            where
45                D: Deserializer<'de>,
46            {
47                struct FieldVisitor;
48
49                impl Visitor<'_> for FieldVisitor {
50                    type Value = Field;
51
52                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
53                        formatter.write_str("`name`, `inputs`, or `outputs`")
54                    }
55
56                    fn visit_str<E>(self, value: &str) -> Result<Field, E>
57                    where
58                        E: de::Error,
59                    {
60                        match value {
61                            "name" => Ok(Field::Name),
62                            "inputs" => Ok(Field::Inputs),
63                            "outputs" => Ok(Field::Outputs),
64                            _ => Err(de::Error::unknown_field(value, FIELDS)),
65                        }
66                    }
67                }
68
69                deserializer.deserialize_identifier(FieldVisitor)
70            }
71        }
72
73        struct CircuitInterfaceVisitor;
74
75        impl<'de> Visitor<'de> for CircuitInterfaceVisitor {
76            type Value = CircuitInterface;
77
78            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
79                formatter.write_str("struct CircuitInterface")
80            }
81
82            fn visit_map<V>(self, mut map: V) -> Result<CircuitInterface, V::Error>
83            where
84                V: MapAccess<'de>,
85            {
86                let mut name = None;
87                let mut inputs = None;
88                let mut outputs = None;
89
90                while let Some(key) = map.next_key()? {
91                    match key {
92                        Field::Name => {
93                            if name.is_some() {
94                                return Err(de::Error::duplicate_field("name"));
95                            }
96                            name = Some(map.next_value()?);
97                        }
98                        Field::Inputs => {
99                            if inputs.is_some() {
100                                return Err(de::Error::duplicate_field("inputs"));
101                            }
102                            inputs = Some(map.next_value()?);
103                        }
104                        Field::Outputs => {
105                            if outputs.is_some() {
106                                return Err(de::Error::duplicate_field("outputs"));
107                            }
108                            outputs = Some(map.next_value()?);
109                        }
110                    }
111                }
112
113                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
114                let inputs = inputs.ok_or_else(|| de::Error::missing_field("inputs"))?;
115                let outputs = outputs.ok_or_else(|| de::Error::missing_field("output"))?;
116
117                Ok(CircuitInterface {
118                    name,
119                    inputs,
120                    outputs,
121                })
122            }
123        }
124
125        const FIELDS: &[&str] = &["name", "inputs", "outputs"];
126        deserializer.deserialize_struct("CircuitInterface", FIELDS, CircuitInterfaceVisitor)
127    }
128}
129
130impl Value {
131    /// Maps scalar size and kind to JSON type name.
132    ///
133    /// Returns standard Rust type names for common sizes (e.g., "u32", "i64"),
134    /// or generic names for non-standard sizes ("scalar" for unsigned, "signed_integer" for
135    /// signed).
136    fn get_scalar_type_name(size_in_bits: usize, kind: ScalarKind) -> &'static str {
137        match kind {
138            ScalarKind::Unsigned => match size_in_bits {
139                8 => "u8",
140                16 => "u16",
141                32 => "u32",
142                64 => "u64",
143                128 => "u128",
144                _ => "scalar",
145            },
146            ScalarKind::Signed => match size_in_bits {
147                8 => "i8",
148                16 => "i16",
149                32 => "i32",
150                64 => "i64",
151                128 => "i128",
152                _ => "signed_integer",
153            },
154        }
155    }
156}
157
158impl Serialize for Value {
159    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160    where
161        S: serde::Serializer,
162    {
163        let json_value = match self {
164            Value::MScalar { size_in_bits } => json!({
165                "type": "mscalar",
166                "size_in_bits": size_in_bits
167            }),
168            Value::MFloat { size_in_bits } => json!({
169                "type": "mfloat",
170                "size_in_bits": size_in_bits
171            }),
172            Value::MBool => json!({
173                "type": "mbool"
174            }),
175            Value::Scalar { size_in_bits, kind } => json!({
176                "type": Value::get_scalar_type_name(*size_in_bits, *kind),
177                "size_in_bits": size_in_bits
178            }),
179            Value::Float { size_in_bits } => json!({
180                "type": "float",
181                "size_in_bits": size_in_bits
182            }),
183            Value::Bool => json!({
184                "type": "bool"
185            }),
186            Value::Ciphertext { size_in_bits } => json!({
187                "type": "ciphertext",
188                "size_in_bits": size_in_bits
189            }),
190            Value::ArcisX25519Pubkey => json!({
191                "type": "arcis_x25519_pubkey",
192            }),
193            Value::Point => json!({
194                "type": "point"
195            }),
196            Value::UnsynchronizedBools { count } => json!({
197                "type": "unsynchronized_bools",
198                "count": count
199            }),
200            Value::Array(vec) => json!({
201                "type": "array",
202                "content": vec
203            }),
204            Value::Tuple(vec) => json!({
205                "type": "tuple",
206                "content": vec
207            }),
208            Value::Struct(vec) => json!({
209                "type": "struct",
210                "content": vec
211            }),
212        };
213        json_value.serialize(serializer)
214    }
215}
216
217impl<'de> Deserialize<'de> for Value {
218    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
219    where
220        D: serde::Deserializer<'de>,
221    {
222        let json_value = JsonValue::deserialize(deserializer)?;
223
224        match json_value {
225            JsonValue::Object(map) => {
226                let type_ = map
227                    .get("type")
228                    .and_then(JsonValue::as_str)
229                    .ok_or_else(|| serde::de::Error::missing_field("type"))?;
230
231                match type_ {
232                    "mscalar" => {
233                        let size_in_bits = map
234                            .get("size_in_bits")
235                            .and_then(JsonValue::as_u64)
236                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
237                        Ok(Value::MScalar {
238                            size_in_bits: size_in_bits as usize,
239                        })
240                    }
241                    "mfloat" => {
242                        let size_in_bits = map
243                            .get("size_in_bits")
244                            .and_then(JsonValue::as_u64)
245                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
246                        Ok(Value::MFloat {
247                            size_in_bits: size_in_bits as usize,
248                        })
249                    }
250                    "mbool" => Ok(Value::MBool),
251                    "u8" => Ok(Value::Scalar {
252                        size_in_bits: 8,
253                        kind: ScalarKind::Unsigned,
254                    }),
255                    "u16" => Ok(Value::Scalar {
256                        size_in_bits: 16,
257                        kind: ScalarKind::Unsigned,
258                    }),
259                    "u32" => Ok(Value::Scalar {
260                        size_in_bits: 32,
261                        kind: ScalarKind::Unsigned,
262                    }),
263                    "u64" => Ok(Value::Scalar {
264                        size_in_bits: 64,
265                        kind: ScalarKind::Unsigned,
266                    }),
267                    "u128" => Ok(Value::Scalar {
268                        size_in_bits: 128,
269                        kind: ScalarKind::Unsigned,
270                    }),
271                    "i8" => Ok(Value::Scalar {
272                        size_in_bits: 8,
273                        kind: ScalarKind::Signed,
274                    }),
275                    "i16" => Ok(Value::Scalar {
276                        size_in_bits: 16,
277                        kind: ScalarKind::Signed,
278                    }),
279                    "i32" => Ok(Value::Scalar {
280                        size_in_bits: 32,
281                        kind: ScalarKind::Signed,
282                    }),
283                    "i64" => Ok(Value::Scalar {
284                        size_in_bits: 64,
285                        kind: ScalarKind::Signed,
286                    }),
287                    "i128" => Ok(Value::Scalar {
288                        size_in_bits: 128,
289                        kind: ScalarKind::Signed,
290                    }),
291                    "scalar" => {
292                        let size_in_bits = map
293                            .get("size_in_bits")
294                            .and_then(JsonValue::as_u64)
295                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
296                        Ok(Value::Scalar {
297                            size_in_bits: size_in_bits as usize,
298                            kind: ScalarKind::Unsigned,
299                        })
300                    }
301                    "signed_integer" => {
302                        let size_in_bits = map
303                            .get("size_in_bits")
304                            .and_then(JsonValue::as_u64)
305                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
306                        Ok(Value::Scalar {
307                            size_in_bits: size_in_bits as usize,
308                            kind: ScalarKind::Signed,
309                        })
310                    }
311                    "ciphertext" => {
312                        let size_in_bits = map
313                            .get("size_in_bits")
314                            .and_then(JsonValue::as_u64)
315                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
316                        Ok(Value::Ciphertext {
317                            size_in_bits: size_in_bits as usize,
318                        })
319                    }
320                    "arcis_x25519_pubkey" => Ok(Value::ArcisX25519Pubkey),
321                    "point" => Ok(Value::Point),
322                    "unsynchronized_bools" => {
323                        let count = map
324                            .get("count")
325                            .and_then(JsonValue::as_u64)
326                            .ok_or_else(|| serde::de::Error::missing_field("count"))?;
327                        Ok(Value::UnsynchronizedBools {
328                            count: count as usize,
329                        })
330                    }
331                    "float" => {
332                        let size_in_bits = map
333                            .get("size_in_bits")
334                            .and_then(JsonValue::as_u64)
335                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
336                        Ok(Value::Float {
337                            size_in_bits: size_in_bits as usize,
338                        })
339                    }
340                    "bool" => Ok(Value::Bool),
341                    "array" | "tuple" | "struct" => {
342                        let content = map
343                            .get("content")
344                            .ok_or_else(|| serde::de::Error::missing_field("content"))?;
345                        let vec: Vec<Value> =
346                            serde_json::from_value(content.clone()).map_err(|e| {
347                                serde::de::Error::custom(format!(
348                                    "Failed to deserialize content: {}",
349                                    e
350                                ))
351                            })?;
352                        match type_ {
353                            "array" => Ok(Value::Array(vec)),
354                            "tuple" => Ok(Value::Tuple(vec)),
355                            "struct" => Ok(Value::Struct(vec)),
356                            _ => unreachable!(),
357                        }
358                    }
359                    _ => Err(serde::de::Error::unknown_variant(
360                        type_,
361                        &[
362                            "mscalar",
363                            "mfloat",
364                            "mbool",
365                            "u8",
366                            "u16",
367                            "u32",
368                            "u64",
369                            "u128",
370                            "i8",
371                            "i16",
372                            "i32",
373                            "i64",
374                            "i128",
375                            "scalar",
376                            "signed_integer",
377                            "float",
378                            "bool",
379                            "array",
380                            "tuple",
381                            "struct",
382                            "ciphertext",
383                            "arcis_x25519_pubkey",
384                            "point",
385                        ],
386                    )),
387                }
388            }
389            _ => Err(serde::de::Error::invalid_type(
390                serde::de::Unexpected::Other("non-object"),
391                &"object",
392            )),
393        }
394    }
395}
396
397#[cfg(test)]
398mod tests {
399    use super::*;
400    use serde_json::json;
401
402    #[test]
403    fn test_mscalar_serialization() {
404        let value = Value::MScalar { size_in_bits: 32 };
405        let serialized = serde_json::to_value(value).unwrap();
406        assert_eq!(
407            serialized,
408            json!({
409                "type": "mscalar",
410                "size_in_bits": 32
411            })
412        );
413    }
414
415    #[test]
416    fn test_unsynchronized_bools_round_trips() {
417        let value = Value::UnsynchronizedBools { count: 1568 };
418        let serialized = serde_json::to_value(value.clone()).unwrap();
419        assert_eq!(
420            serialized,
421            json!({
422                "type": "unsynchronized_bools",
423                "count": 1568
424            })
425        );
426        assert_eq!(serde_json::from_value::<Value>(serialized).unwrap(), value);
427    }
428
429    /// It maps to a single on-chain parameter, however many bits it carries -- the property the
430    /// argument matcher relies on.
431    #[test]
432    fn test_unsynchronized_bools_is_one_value() {
433        assert_eq!(
434            Value::UnsynchronizedBools { count: 1568 }.size_in_scalars(),
435            1
436        );
437    }
438
439    #[test]
440    fn test_mbool_serialization() {
441        let value = Value::MBool;
442        let serialized = serde_json::to_value(value).unwrap();
443        assert_eq!(
444            serialized,
445            json!({
446                "type": "mbool"
447            })
448        );
449    }
450
451    #[test]
452    fn test_bool_serialization() {
453        let value = Value::Bool;
454        let serialized = serde_json::to_value(value).unwrap();
455        assert_eq!(
456            serialized,
457            json!({
458                "type": "bool"
459            })
460        );
461    }
462
463    #[test]
464    fn test_array_serialization() {
465        let value = Value::Array(vec![
466            Value::Scalar {
467                size_in_bits: 60,
468                kind: ScalarKind::Unsigned,
469            },
470            Value::Bool,
471        ]);
472        let serialized = serde_json::to_value(value).unwrap();
473        assert_eq!(
474            serialized,
475            json!({
476                "type": "array",
477                "content": [
478                    {
479                        "type": "scalar",
480                        "size_in_bits": 60
481                    },
482                    {
483                        "type": "bool"
484                    }
485                ]
486            })
487        );
488    }
489
490    #[test]
491    fn test_nested_structure_serialization() {
492        let value = Value::Struct(vec![
493            Value::Tuple(vec![Value::MScalar { size_in_bits: 32 }, Value::MBool]),
494            Value::Array(vec![
495                Value::Scalar {
496                    size_in_bits: 64,
497                    kind: ScalarKind::Unsigned,
498                },
499                Value::Bool,
500            ]),
501        ]);
502        let serialized = serde_json::to_string(&value).unwrap();
503        let deserialized: Value = serde_json::from_str(&serialized).unwrap();
504        assert_eq!(value, deserialized);
505    }
506
507    #[test]
508    fn test_mscalar_deserialization() {
509        let json = r#"{"type": "mscalar", "size_in_bits": 32}"#;
510        let deserialized: Value = serde_json::from_str(json).unwrap();
511        assert_eq!(deserialized, Value::MScalar { size_in_bits: 32 });
512    }
513
514    #[test]
515    fn test_array_deserialization() {
516        let json = r#"
517        {
518            "type": "array",
519            "content": [
520                {"type": "scalar", "size_in_bits": 64},
521                {"type": "bool"}
522            ]
523        }"#;
524        let deserialized: Value = serde_json::from_str(json).unwrap();
525        assert_eq!(
526            deserialized,
527            Value::Array(vec![
528                Value::Scalar {
529                    size_in_bits: 64,
530                    kind: ScalarKind::Unsigned,
531                },
532                Value::Bool,
533            ])
534        );
535    }
536
537    #[test]
538    fn test_invalid_type_deserialization() {
539        let json = r#"{"type": "invalid_type"}"#;
540        let result: Result<Value, _> = serde_json::from_str(json);
541        assert!(result.is_err());
542    }
543
544    #[test]
545    fn test_missing_size_in_bits_deserialization() {
546        let json = r#"{"type": "mscalar"}"#;
547        let result: Result<Value, _> = serde_json::from_str(json);
548        assert!(result.is_err());
549    }
550
551    #[test]
552    fn test_plaintext_type_serialization() {
553        // Test all standard numeric sizes (unsigned)
554        let test_cases = [
555            (
556                Value::Scalar {
557                    size_in_bits: 8,
558                    kind: ScalarKind::Unsigned,
559                },
560                "u8",
561            ),
562            (
563                Value::Scalar {
564                    size_in_bits: 16,
565                    kind: ScalarKind::Unsigned,
566                },
567                "u16",
568            ),
569            (
570                Value::Scalar {
571                    size_in_bits: 32,
572                    kind: ScalarKind::Unsigned,
573                },
574                "u32",
575            ),
576            (
577                Value::Scalar {
578                    size_in_bits: 64,
579                    kind: ScalarKind::Unsigned,
580                },
581                "u64",
582            ),
583            (
584                Value::Scalar {
585                    size_in_bits: 128,
586                    kind: ScalarKind::Unsigned,
587                },
588                "u128",
589            ),
590            // Test non-standard size falls back to scalar
591            (
592                Value::Scalar {
593                    size_in_bits: 24,
594                    kind: ScalarKind::Unsigned,
595                },
596                "scalar",
597            ),
598        ];
599
600        for (value, expected_type) in test_cases {
601            // Test serialization
602            let serialized = serde_json::to_value(&value).unwrap();
603            let expected = match &value {
604                Value::Scalar { size_in_bits, .. } => json!({
605                    "type": expected_type,
606                    "size_in_bits": size_in_bits
607                }),
608                Value::Bool => json!({
609                    "type": expected_type
610                }),
611                _ => unreachable!(),
612            };
613            assert_eq!(serialized, expected);
614
615            // Test deserialization
616            let json = serde_json::to_string(&expected).unwrap();
617            let deserialized: Value = serde_json::from_str(&json).unwrap();
618            assert_eq!(deserialized, value);
619        }
620    }
621
622    #[test]
623    fn test_signed_integer_serialization() {
624        let test_cases = [
625            (
626                Value::Scalar {
627                    size_in_bits: 8,
628                    kind: ScalarKind::Signed,
629                },
630                "i8",
631            ),
632            (
633                Value::Scalar {
634                    size_in_bits: 16,
635                    kind: ScalarKind::Signed,
636                },
637                "i16",
638            ),
639            (
640                Value::Scalar {
641                    size_in_bits: 32,
642                    kind: ScalarKind::Signed,
643                },
644                "i32",
645            ),
646            (
647                Value::Scalar {
648                    size_in_bits: 64,
649                    kind: ScalarKind::Signed,
650                },
651                "i64",
652            ),
653            (
654                Value::Scalar {
655                    size_in_bits: 128,
656                    kind: ScalarKind::Signed,
657                },
658                "i128",
659            ),
660            (
661                Value::Scalar {
662                    size_in_bits: 24,
663                    kind: ScalarKind::Signed,
664                },
665                "signed_integer",
666            ),
667        ];
668
669        for (value, expected_type) in test_cases {
670            // Test serialization
671            let serialized = serde_json::to_value(&value).unwrap();
672            let expected = json!({
673                "type": expected_type,
674                "size_in_bits": match &value {
675                    Value::Scalar { size_in_bits, .. } => size_in_bits,
676                    _ => unreachable!(),
677                }
678            });
679            assert_eq!(serialized, expected);
680
681            // Test deserialization
682            let json = serde_json::to_string(&expected).unwrap();
683            let deserialized: Value = serde_json::from_str(&json).unwrap();
684            assert_eq!(deserialized, value);
685        }
686    }
687
688    #[test]
689    fn test_backward_compatibility() {
690        // Test that old JSON without 'kind' field defaults to unsigned
691        let old_json_cases = [
692            (r#"{"type": "u8", "size_in_bits": 8}"#, 8),
693            (r#"{"type": "u16", "size_in_bits": 16}"#, 16),
694            (r#"{"type": "u32", "size_in_bits": 32}"#, 32),
695            (r#"{"type": "u64", "size_in_bits": 64}"#, 64),
696            (r#"{"type": "u128", "size_in_bits": 128}"#, 128),
697            (r#"{"type": "scalar", "size_in_bits": 24}"#, 24),
698        ];
699
700        for (json, expected_size) in old_json_cases {
701            let deserialized: Value = serde_json::from_str(json).unwrap();
702            assert_eq!(
703                deserialized,
704                Value::Scalar {
705                    size_in_bits: expected_size,
706                    kind: ScalarKind::Unsigned
707                }
708            );
709        }
710    }
711
712    #[test]
713    fn test_mixed_signed_unsigned_serialization() {
714        // Test that signed and unsigned integers serialize differently
715        let unsigned = Value::Scalar {
716            size_in_bits: 32,
717            kind: ScalarKind::Unsigned,
718        };
719        let signed = Value::Scalar {
720            size_in_bits: 32,
721            kind: ScalarKind::Signed,
722        };
723
724        let unsigned_json = serde_json::to_value(&unsigned).unwrap();
725        let signed_json = serde_json::to_value(&signed).unwrap();
726
727        assert_eq!(
728            unsigned_json,
729            json!({
730                "type": "u32",
731                "size_in_bits": 32
732            })
733        );
734        assert_eq!(
735            signed_json,
736            json!({
737                "type": "i32",
738                "size_in_bits": 32
739            })
740        );
741
742        // Ensure they're different
743        assert_ne!(unsigned_json, signed_json);
744    }
745}