11
11
//! The trait `SerDeShelleyFileFormat` can be implemented for any structure that implements
12
12
//! `Serialize` and `Deserialize`.
13
13
14
+ use anyhow:: { anyhow, Context } ;
14
15
use hex:: FromHex ;
15
16
use kes_summed_ed25519:: kes:: Sum6Kes ;
16
17
use kes_summed_ed25519:: traits:: KesSk ;
@@ -22,6 +23,8 @@ use std::io::Write;
22
23
use std:: path:: Path ;
23
24
use thiserror:: Error ;
24
25
26
+ use crate :: StdError ;
27
+
25
28
/// We need to create this struct because the design of Sum6Kes takes
26
29
/// a reference to a mutable pointer. It is therefore not possible to
27
30
/// implement Ser/Deser using serde.
@@ -33,22 +36,8 @@ pub struct Sum6KesBytes(#[serde(with = "As::<Bytes>")] pub [u8; 612]);
33
36
34
37
/// Parse error
35
38
#[ derive( Error , Debug ) ]
36
- pub enum ParseError {
37
- #[ error( "io error: `{0}`" ) ]
38
- IO ( #[ from] std:: io:: Error ) ,
39
-
40
- #[ error( "JSON parse error: `{0}`" ) ]
41
- JsonFormat ( #[ from] serde_json:: Error ) ,
42
-
43
- #[ error( "CBOR hex codec error: `{0}`" ) ]
44
- CborHex ( #[ from] hex:: FromHexError ) ,
45
-
46
- #[ error( "CBOR parse error: `{0}`" ) ]
47
- CborFormat ( #[ from] serde_cbor:: Error ) ,
48
-
49
- #[ error( "Invalid KES format" ) ]
50
- KesFormat ,
51
- }
39
+ #[ error( "Codec parse error: `{0:?}`" ) ]
40
+ pub struct CodecParseError ( StdError ) ;
52
41
53
42
/// Fields for a shelley formatted file (holds for vkeys, skeys or certs)
54
43
#[ derive( Clone , Debug , Default , Serialize , Deserialize ) ]
@@ -71,30 +60,48 @@ pub trait SerDeShelleyFileFormat: Serialize + DeserializeOwned {
71
60
72
61
/// Deserialize a type `T: Serialize + DeserializeOwned` from file following Cardano
73
62
/// Shelley file format.
74
- fn from_file < P : AsRef < Path > > ( path : P ) -> Result < Self , ParseError > {
75
- let data = fs:: read_to_string ( path) ?;
76
- let file: ShelleyFileFormat = serde_json:: from_str ( & data) ?;
77
- let hex_vector = Vec :: from_hex ( file. cbor_hex ) ?;
63
+ fn from_file < P : AsRef < Path > > ( path : P ) -> Result < Self , CodecParseError > {
64
+ let data = fs:: read_to_string ( path)
65
+ . with_context ( || "SerDeShelleyFileFormat can not read data from file {}" )
66
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
67
+ let file: ShelleyFileFormat = serde_json:: from_str ( & data)
68
+ . with_context ( || "SerDeShelleyFileFormat can not unserialize json data" )
69
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
70
+ let hex_vector = Vec :: from_hex ( file. cbor_hex )
71
+ . with_context ( || "SerDeShelleyFileFormat can not unserialize hex data" )
72
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
73
+ let a: Self = serde_cbor:: from_slice ( & hex_vector)
74
+ . with_context ( || "SerDeShelleyFileFormat can not unserialize cbor data" )
75
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
78
76
79
- let a: Self = serde_cbor:: from_slice ( & hex_vector) ?;
80
77
Ok ( a)
81
78
}
82
79
83
80
/// Serialize a type `T: Serialize + DeserializeOwned` to file following Cardano
84
81
/// Shelley file format.
85
- fn to_file < P : AsRef < Path > > ( & self , path : P ) -> Result < ( ) , ParseError > {
86
- let cbor_string = hex:: encode ( serde_cbor:: to_vec ( & self ) ?) ;
82
+ fn to_file < P : AsRef < Path > > ( & self , path : P ) -> Result < ( ) , CodecParseError > {
83
+ let cbor_string = hex:: encode (
84
+ serde_cbor:: to_vec ( & self )
85
+ . with_context ( || "SerDeShelleyFileFormat can not serialize data to cbor" )
86
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?,
87
+ ) ;
87
88
88
89
let file_format = ShelleyFileFormat {
89
90
file_type : Self :: TYPE . to_string ( ) ,
90
91
description : Self :: DESCRIPTION . to_string ( ) ,
91
92
cbor_hex : cbor_string,
92
93
} ;
93
94
94
- let mut file = fs:: File :: create ( path) ?;
95
- let json_str = serde_json:: to_string ( & file_format) ?;
95
+ let mut file = fs:: File :: create ( path)
96
+ . with_context ( || "SerDeShelleyFileFormat can not create file" )
97
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
98
+ let json_str = serde_json:: to_string ( & file_format)
99
+ . with_context ( || "SerDeShelleyFileFormat can not serialize data to json" )
100
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
96
101
97
- write ! ( file, "{json_str}" ) ?;
102
+ write ! ( file, "{json_str}" )
103
+ . with_context ( || "SerDeShelleyFileFormat can not write data to file" )
104
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
98
105
Ok ( ( ) )
99
106
}
100
107
}
@@ -106,10 +113,16 @@ impl SerDeShelleyFileFormat for Sum6KesBytes {
106
113
/// Deserialize a Cardano key from file. Cardano KES key Shelley format does not
107
114
/// contain the period (it is always zero). Therefore we need to include it in the
108
115
/// deserialisation.
109
- fn from_file < P : AsRef < Path > > ( path : P ) -> Result < Self , ParseError > {
110
- let data = fs:: read_to_string ( path) ?;
111
- let file: ShelleyFileFormat = serde_json:: from_str ( & data) ?;
112
- let mut hex_vector = Vec :: from_hex ( file. cbor_hex ) ?;
116
+ fn from_file < P : AsRef < Path > > ( path : P ) -> Result < Self , CodecParseError > {
117
+ let data = fs:: read_to_string ( path)
118
+ . with_context ( || "Sum6KesBytes can not read data from file" )
119
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
120
+ let file: ShelleyFileFormat = serde_json:: from_str ( & data)
121
+ . with_context ( || "Sum6KesBytes can not unserialize json data" )
122
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
123
+ let mut hex_vector = Vec :: from_hex ( file. cbor_hex )
124
+ . with_context ( || "Sum6KesBytes can not unserialize hex data" )
125
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
113
126
114
127
// We check whether the serialisation was performed by the haskell library or the rust library
115
128
if ( hex_vector[ 2 ] & 4u8 ) == 0 {
@@ -119,16 +132,18 @@ impl SerDeShelleyFileFormat for Sum6KesBytes {
119
132
hex_vector. extend_from_slice ( & [ 0u8 ; 4 ] ) ;
120
133
}
121
134
122
- let a: Self = serde_cbor:: from_slice ( & hex_vector) ?;
135
+ let a: Self = serde_cbor:: from_slice ( & hex_vector)
136
+ . with_context ( || "Sum6KesBytes can not unserialize cbor data" )
137
+ . map_err ( |e| CodecParseError ( anyhow ! ( e) ) ) ?;
123
138
Ok ( a)
124
139
}
125
140
}
126
141
127
142
impl < ' a > TryFrom < & ' a mut Sum6KesBytes > for Sum6Kes < ' a > {
128
- type Error = ParseError ;
143
+ type Error = CodecParseError ;
129
144
130
145
fn try_from ( value : & ' a mut Sum6KesBytes ) -> Result < Self , Self :: Error > {
131
- Self :: from_bytes ( & mut value. 0 ) . map_err ( |_| ParseError :: KesFormat )
146
+ Self :: from_bytes ( & mut value. 0 ) . map_err ( |e| CodecParseError ( anyhow ! ( format! ( "{e:?}" ) ) ) )
132
147
}
133
148
}
134
149
0 commit comments