@@ -91,6 +91,45 @@ impl Peer {
9191#[ derive( PartialEq , Eq , Hash , Clone , Debug , PartialOrd , Ord , Copy ) ]
9292pub struct Id ( pub [ u8 ; 20 ] ) ;
9393
94+ #[ derive( Debug ) ]
95+ pub enum IdConversionError {
96+ NotEnoughBytes ,
97+ TooManyBytes ,
98+ }
99+
100+ impl Id {
101+ /// # Panics
102+ ///
103+ /// Will panic if byte slice does not contains the exact amount of bytes need for the `Id`.
104+ #[ must_use]
105+ pub fn from_bytes ( bytes : & [ u8 ] ) -> Self {
106+ assert_eq ! ( bytes. len( ) , 20 ) ;
107+ let mut ret = Id ( [ 0u8 ; 20 ] ) ;
108+ ret. 0 . clone_from_slice ( bytes) ;
109+ ret
110+ }
111+ }
112+
113+ impl From < [ u8 ; 20 ] > for Id {
114+ fn from ( bytes : [ u8 ; 20 ] ) -> Self {
115+ Id ( bytes)
116+ }
117+ }
118+
119+ impl TryFrom < Vec < u8 > > for Id {
120+ type Error = IdConversionError ;
121+
122+ fn try_from ( bytes : Vec < u8 > ) -> Result < Self , Self :: Error > {
123+ if bytes. len ( ) < 20 {
124+ return Err ( IdConversionError :: NotEnoughBytes ) ;
125+ }
126+ if bytes. len ( ) > 20 {
127+ return Err ( IdConversionError :: TooManyBytes ) ;
128+ }
129+ Ok ( Self :: from_bytes ( & bytes) )
130+ }
131+ }
132+
94133impl std:: fmt:: Display for Id {
95134 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
96135 match self . to_hex_string ( ) {
@@ -239,6 +278,75 @@ mod test {
239278 mod torrent_peer_id {
240279 use crate :: tracker:: peer;
241280
281+ #[ test]
282+ fn should_be_instantiated_from_a_byte_slice ( ) {
283+ let id = peer:: Id :: from_bytes ( & [
284+ 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 ,
285+ ] ) ;
286+
287+ let expected_id = peer:: Id ( [
288+ 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 ,
289+ ] ) ;
290+
291+ assert_eq ! ( id, expected_id) ;
292+ }
293+
294+ #[ test]
295+ #[ should_panic]
296+ fn should_fail_trying_to_instantiate_from_a_byte_slice_with_less_than_20_bytes ( ) {
297+ let less_than_20_bytes = [ 0 ; 19 ] ;
298+ let _ = peer:: Id :: from_bytes ( & less_than_20_bytes) ;
299+ }
300+
301+ #[ test]
302+ #[ should_panic]
303+ fn should_fail_trying_to_instantiate_from_a_byte_slice_with_more_than_20_bytes ( ) {
304+ let more_than_20_bytes = [ 0 ; 21 ] ;
305+ let _ = peer:: Id :: from_bytes ( & more_than_20_bytes) ;
306+ }
307+
308+ #[ test]
309+ fn should_be_converted_from_a_20_byte_array ( ) {
310+ let id = peer:: Id :: from ( [
311+ 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 ,
312+ ] ) ;
313+
314+ let expected_id = peer:: Id ( [
315+ 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 ,
316+ ] ) ;
317+
318+ assert_eq ! ( id, expected_id) ;
319+ }
320+
321+ #[ test]
322+ fn should_be_converted_from_a_byte_vector ( ) {
323+ let id = peer:: Id :: try_from (
324+ [
325+ 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 ,
326+ ]
327+ . to_vec ( ) ,
328+ )
329+ . unwrap ( ) ;
330+
331+ let expected_id = peer:: Id ( [
332+ 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 , 0 , 159 , 146 , 150 ,
333+ ] ) ;
334+
335+ assert_eq ! ( id, expected_id) ;
336+ }
337+
338+ #[ test]
339+ #[ should_panic]
340+ fn should_fail_trying_to_convert_from_a_byte_vector_with_less_than_20_bytes ( ) {
341+ let _ = peer:: Id :: try_from ( [ 0 ; 19 ] . to_vec ( ) ) . unwrap ( ) ;
342+ }
343+
344+ #[ test]
345+ #[ should_panic]
346+ fn should_fail_trying_to_convert_from_a_byte_vector_with_more_than_20_bytes ( ) {
347+ let _ = peer:: Id :: try_from ( [ 0 ; 21 ] . to_vec ( ) ) . unwrap ( ) ;
348+ }
349+
242350 #[ test]
243351 fn should_be_converted_to_hex_string ( ) {
244352 let id = peer:: Id ( * b"-qB00000000000000000" ) ;
0 commit comments