Define serde's Serialize/Deserialize for Program<DeBrujin>
This will be useful to re-use this behavior in other structure that contains a Program<DeBruijn> without having to manually serialize or deserialize the entire structure.
This commit is contained in:
		
							parent
							
								
									4588ccd040
								
							
						
					
					
						commit
						cab59c188a
					
				|  | @ -1,6 +1,20 @@ | |||
| use std::{fmt::Display, rc::Rc}; | ||||
| use std::{ | ||||
|     fmt::{self, Display}, | ||||
|     rc::Rc, | ||||
| }; | ||||
| 
 | ||||
| use pallas_primitives::{alonzo::PlutusData, babbage::Language}; | ||||
| use serde::{ | ||||
|     self, | ||||
|     de::{self, Deserialize, Deserializer, MapAccess, Visitor}, | ||||
|     ser::{Serialize, SerializeStruct, Serializer}, | ||||
| }; | ||||
| 
 | ||||
| use pallas_addresses::{Network, ShelleyAddress, ShelleyDelegationPart, ShelleyPaymentPart}; | ||||
| use pallas_primitives::{ | ||||
|     alonzo::PlutusData, | ||||
|     babbage::{self as cardano, Language}, | ||||
| }; | ||||
| use pallas_traverse::ComputeHash; | ||||
| 
 | ||||
| use crate::{ | ||||
|     builtins::DefaultFunction, | ||||
|  | @ -79,6 +93,81 @@ where | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Serialize for Program<DeBruijn> { | ||||
|     fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | ||||
|         let cbor = self.to_cbor().unwrap(); | ||||
|         let mut s = serializer.serialize_struct("Program<DeBruijn>", 2)?; | ||||
|         s.serialize_field("compiledCode", &hex::encode(&cbor))?; | ||||
|         s.serialize_field("hash", &cardano::PlutusV2Script(cbor.into()).compute_hash())?; | ||||
|         s.end() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'a> Deserialize<'a> for Program<DeBruijn> { | ||||
|     fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> { | ||||
|         #[derive(serde::Deserialize)] | ||||
|         #[serde(field_identifier, rename_all = "camelCase")] | ||||
|         enum Fields { | ||||
|             CompiledCode, | ||||
|         } | ||||
| 
 | ||||
|         struct ProgramVisitor; | ||||
| 
 | ||||
|         impl<'a> Visitor<'a> for ProgramVisitor { | ||||
|             type Value = Program<DeBruijn>; | ||||
| 
 | ||||
|             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | ||||
|                 formatter.write_str("Program<Visitor>") | ||||
|             } | ||||
| 
 | ||||
|             fn visit_map<V>(self, mut map: V) -> Result<Program<DeBruijn>, V::Error> | ||||
|             where | ||||
|                 V: MapAccess<'a>, | ||||
|             { | ||||
|                 let mut compiled_code: Option<String> = None; | ||||
|                 while let Some(key) = map.next_key()? { | ||||
|                     match key { | ||||
|                         Fields::CompiledCode => { | ||||
|                             if compiled_code.is_some() { | ||||
|                                 return Err(de::Error::duplicate_field("compiledCode")); | ||||
|                             } | ||||
|                             compiled_code = Some(map.next_value()?); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 let compiled_code = | ||||
|                     compiled_code.ok_or_else(|| de::Error::missing_field("compiledCode"))?; | ||||
| 
 | ||||
|                 let mut cbor_buffer = Vec::new(); | ||||
|                 let mut flat_buffer = Vec::new(); | ||||
| 
 | ||||
|                 Program::<DeBruijn>::from_hex(&compiled_code, &mut cbor_buffer, &mut flat_buffer) | ||||
|                     .map_err(|e| { | ||||
|                         de::Error::invalid_value( | ||||
|                             de::Unexpected::Other(&format!("{}", e)), | ||||
|                             &"a base16-encoded CBOR-serialized UPLC program", | ||||
|                         ) | ||||
|                     }) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const FIELDS: &[&str] = &["compiledCode"]; | ||||
|         deserializer.deserialize_struct("Program<DeBruijn>", FIELDS, ProgramVisitor) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Program<DeBruijn> { | ||||
|     pub fn address(&self, network: Network, delegation: ShelleyDelegationPart) -> ShelleyAddress { | ||||
|         let cbor = self.to_cbor().unwrap(); | ||||
|         let validator_hash = cardano::PlutusV2Script(cbor.into()).compute_hash(); | ||||
|         ShelleyAddress::new( | ||||
|             network, | ||||
|             ShelleyPaymentPart::Script(validator_hash), | ||||
|             delegation, | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// This represents a term in Untyped Plutus Core.
 | ||||
| /// We need a generic type for the different forms that a program may be in.
 | ||||
| /// Specifically, `Var` and `parameter_name` in `Lambda` can be a `Name`,
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 KtorZ
						KtorZ