interledger_packet/
packet.rs

1use hex;
2use std::fmt;
3use std::io::prelude::*;
4use std::io::Cursor;
5use std::str;
6use std::time::SystemTime;
7
8use byteorder::{BigEndian, ReadBytesExt};
9use bytes::{BufMut, BytesMut};
10use chrono::{DateTime, TimeZone, Utc};
11
12use super::oer::{self, BufOerExt, MutBufOerExt};
13use super::{Address, ErrorCode, ParseError};
14use std::convert::TryFrom;
15
16const AMOUNT_LEN: usize = 8;
17const EXPIRY_LEN: usize = 17;
18const CONDITION_LEN: usize = 32;
19const FULFILLMENT_LEN: usize = 32;
20const ERROR_CODE_LEN: usize = 3;
21
22static INTERLEDGER_TIMESTAMP_FORMAT: &str = "%Y%m%d%H%M%S%3f";
23
24#[derive(Clone, Copy, Debug, PartialEq)]
25#[repr(u8)]
26pub enum PacketType {
27    Prepare = 12,
28    Fulfill = 13,
29    Reject = 14,
30}
31
32// Gets the packet type from a u8 array
33impl TryFrom<&[u8]> for PacketType {
34    type Error = ParseError;
35
36    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
37        match bytes.first() {
38            Some(&12) => Ok(PacketType::Prepare),
39            Some(&13) => Ok(PacketType::Fulfill),
40            Some(&14) => Ok(PacketType::Reject),
41            _ => Err(ParseError::InvalidPacket(format!(
42                "Unknown packet type: {:?}",
43                bytes,
44            ))),
45        }
46    }
47}
48
49impl TryFrom<u8> for PacketType {
50    type Error = ParseError;
51
52    fn try_from(byte: u8) -> Result<Self, Self::Error> {
53        match byte {
54            12 => Ok(PacketType::Prepare),
55            13 => Ok(PacketType::Fulfill),
56            14 => Ok(PacketType::Reject),
57            _ => Err(ParseError::InvalidPacket(format!(
58                "Unknown packet type: {:?}",
59                byte,
60            ))),
61        }
62    }
63}
64
65#[derive(Debug, PartialEq, Clone)]
66pub enum Packet {
67    Prepare(Prepare),
68    Fulfill(Fulfill),
69    Reject(Reject),
70}
71
72impl TryFrom<BytesMut> for Packet {
73    type Error = ParseError;
74
75    fn try_from(buffer: BytesMut) -> Result<Self, Self::Error> {
76        match buffer.first() {
77            Some(&12) => Ok(Packet::Prepare(Prepare::try_from(buffer)?)),
78            Some(&13) => Ok(Packet::Fulfill(Fulfill::try_from(buffer)?)),
79            Some(&14) => Ok(Packet::Reject(Reject::try_from(buffer)?)),
80            _ => Err(ParseError::InvalidPacket(format!(
81                "Unknown packet type: {:?}",
82                buffer.first(),
83            ))),
84        }
85    }
86}
87
88impl From<Packet> for BytesMut {
89    fn from(packet: Packet) -> Self {
90        match packet {
91            Packet::Prepare(prepare) => prepare.into(),
92            Packet::Fulfill(fulfill) => fulfill.into(),
93            Packet::Reject(reject) => reject.into(),
94        }
95    }
96}
97
98impl From<Prepare> for Packet {
99    fn from(prepare: Prepare) -> Self {
100        Packet::Prepare(prepare)
101    }
102}
103
104impl From<Fulfill> for Packet {
105    fn from(fulfill: Fulfill) -> Self {
106        Packet::Fulfill(fulfill)
107    }
108}
109
110impl From<Reject> for Packet {
111    fn from(reject: Reject) -> Self {
112        Packet::Reject(reject)
113    }
114}
115
116#[derive(PartialEq, Clone)]
117pub struct Prepare {
118    buffer: BytesMut,
119    content_offset: usize,
120    destination: Address,
121    amount: u64,
122    expires_at: SystemTime,
123    data_offset: usize,
124}
125
126#[derive(Clone, Debug, PartialEq)]
127pub struct PrepareBuilder<'a> {
128    pub amount: u64,
129    pub expires_at: SystemTime,
130    pub execution_condition: &'a [u8; 32],
131    pub destination: Address,
132    pub data: &'a [u8],
133}
134
135impl TryFrom<BytesMut> for Prepare {
136    type Error = ParseError;
137
138    fn try_from(buffer: BytesMut) -> Result<Self, Self::Error> {
139        let (content_offset, mut content) = deserialize_envelope(PacketType::Prepare, &buffer)?;
140        let content_len = content.len();
141        let amount = content.read_u64::<BigEndian>()?;
142
143        let mut expires_at = [0x00; 17];
144        content.read_exact(&mut expires_at)?;
145        let expires_at = str::from_utf8(&expires_at[..])?;
146        let expires_at: DateTime<Utc> =
147            Utc.datetime_from_str(&expires_at, INTERLEDGER_TIMESTAMP_FORMAT)?;
148        let expires_at = SystemTime::from(expires_at);
149
150        // Skip execution condition.
151        content.skip(CONDITION_LEN)?;
152
153        let destination = Address::try_from(content.read_var_octet_string()?)?;
154
155        // Skip the data.
156        let data_offset = content_offset + content_len - content.len();
157        content.skip_var_octet_string()?;
158
159        Ok(Prepare {
160            buffer,
161            content_offset,
162            destination,
163            amount,
164            expires_at,
165            data_offset,
166        })
167    }
168}
169
170impl Prepare {
171    #[inline]
172    pub fn amount(&self) -> u64 {
173        self.amount
174    }
175
176    #[inline]
177    pub fn set_amount(&mut self, amount: u64) {
178        self.amount = amount;
179        let mut cursor = Cursor::new(&mut self.buffer);
180        cursor.set_position(self.content_offset as u64);
181        cursor.put_u64_be(amount);
182    }
183
184    #[inline]
185    pub fn expires_at(&self) -> SystemTime {
186        self.expires_at
187    }
188
189    #[inline]
190    pub fn set_expires_at(&mut self, expires_at: SystemTime) {
191        self.expires_at = expires_at;
192        let offset = self.content_offset + AMOUNT_LEN;
193        write!(
194            &mut self.buffer[offset..],
195            "{}",
196            DateTime::<Utc>::from(expires_at).format(INTERLEDGER_TIMESTAMP_FORMAT),
197        )
198        .unwrap();
199    }
200
201    /// The returned value always has a length of 32.
202    #[inline]
203    pub fn execution_condition(&self) -> &[u8] {
204        let begin = self.content_offset + AMOUNT_LEN + EXPIRY_LEN;
205        let end = begin + CONDITION_LEN;
206        &self.buffer[begin..end]
207    }
208
209    #[inline]
210    pub fn destination(&self) -> Address {
211        self.destination.clone()
212    }
213
214    #[inline]
215    pub fn data(&self) -> &[u8] {
216        (&self.buffer[self.data_offset..])
217            .peek_var_octet_string()
218            .unwrap()
219    }
220
221    #[inline]
222    pub fn into_data(mut self) -> BytesMut {
223        oer::extract_var_octet_string(self.buffer.split_off(self.data_offset)).unwrap()
224    }
225}
226
227impl AsRef<[u8]> for Prepare {
228    #[inline]
229    fn as_ref(&self) -> &[u8] {
230        &self.buffer
231    }
232}
233
234impl From<Prepare> for BytesMut {
235    fn from(prepare: Prepare) -> Self {
236        prepare.buffer
237    }
238}
239
240impl fmt::Debug for Prepare {
241    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
242        formatter
243            .debug_struct("Prepare")
244            .field("destination", &self.destination())
245            .field("amount", &self.amount())
246            .field(
247                "expires_at",
248                &DateTime::<Utc>::from(self.expires_at()).to_rfc3339(),
249            )
250            .field(
251                "execution_condition",
252                &hex::encode(self.execution_condition()),
253            )
254            .field("data_length", &self.data().len())
255            .finish()
256    }
257}
258
259impl<'a> PrepareBuilder<'a> {
260    pub fn build(&self) -> Prepare {
261        const STATIC_LEN: usize = AMOUNT_LEN + EXPIRY_LEN + CONDITION_LEN;
262        let destination_size = oer::predict_var_octet_string(self.destination.len());
263        let data_size = oer::predict_var_octet_string(self.data.len());
264        let content_len = STATIC_LEN + destination_size + data_size;
265        let buf_size = 1 + oer::predict_var_octet_string(content_len);
266        let mut buffer = BytesMut::with_capacity(buf_size);
267
268        buffer.put_u8(PacketType::Prepare as u8);
269        buffer.put_var_octet_string_length(content_len);
270        let content_offset = buffer.len();
271        buffer.put_u64_be(self.amount);
272
273        let mut writer = buffer.writer();
274        write!(
275            writer,
276            "{}",
277            DateTime::<Utc>::from(self.expires_at).format(INTERLEDGER_TIMESTAMP_FORMAT),
278        )
279        .unwrap();
280        let mut buffer = writer.into_inner();
281
282        buffer.put_slice(&self.execution_condition[..]);
283        buffer.put_var_octet_string::<&[u8]>(self.destination.as_ref());
284        buffer.put_var_octet_string(self.data);
285
286        Prepare {
287            buffer,
288            content_offset,
289            destination: self.destination.clone(),
290            amount: self.amount,
291            expires_at: self.expires_at,
292            data_offset: buf_size - data_size,
293        }
294    }
295}
296
297#[derive(PartialEq, Clone)]
298pub struct Fulfill {
299    buffer: BytesMut,
300    content_offset: usize,
301}
302
303#[derive(Clone, Debug, PartialEq)]
304pub struct FulfillBuilder<'a> {
305    pub fulfillment: &'a [u8; 32],
306    pub data: &'a [u8],
307}
308
309impl TryFrom<BytesMut> for Fulfill {
310    type Error = ParseError;
311
312    fn try_from(buffer: BytesMut) -> Result<Self, Self::Error> {
313        let (content_offset, mut content) = deserialize_envelope(PacketType::Fulfill, &buffer)?;
314
315        content.skip(FULFILLMENT_LEN)?;
316        content.skip_var_octet_string()?;
317
318        Ok(Fulfill {
319            buffer,
320            content_offset,
321        })
322    }
323}
324
325impl Fulfill {
326    /// The returned value always has a length of 32.
327    #[inline]
328    pub fn fulfillment(&self) -> &[u8] {
329        let begin = self.content_offset;
330        let end = begin + FULFILLMENT_LEN;
331        &self.buffer[begin..end]
332    }
333
334    #[inline]
335    pub fn data(&self) -> &[u8] {
336        let data_offset = self.content_offset + FULFILLMENT_LEN;
337        (&self.buffer[data_offset..])
338            .peek_var_octet_string()
339            .unwrap()
340    }
341
342    #[inline]
343    pub fn into_data(mut self) -> BytesMut {
344        let data_offset = self.content_offset + FULFILLMENT_LEN;
345        oer::extract_var_octet_string(self.buffer.split_off(data_offset)).unwrap()
346    }
347}
348
349impl AsRef<[u8]> for Fulfill {
350    #[inline]
351    fn as_ref(&self) -> &[u8] {
352        &self.buffer
353    }
354}
355
356impl From<Fulfill> for BytesMut {
357    fn from(fulfill: Fulfill) -> Self {
358        fulfill.buffer
359    }
360}
361
362impl fmt::Debug for Fulfill {
363    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
364        formatter
365            .debug_struct("Fulfill")
366            .field("fulfillment", &hex::encode(self.fulfillment()))
367            .field("data_length", &self.data().len())
368            .finish()
369    }
370}
371
372impl<'a> FulfillBuilder<'a> {
373    pub fn build(&self) -> Fulfill {
374        let data_size = oer::predict_var_octet_string(self.data.len());
375        let content_len = FULFILLMENT_LEN + data_size;
376        let buf_size = 1 + oer::predict_var_octet_string(content_len);
377        let mut buffer = BytesMut::with_capacity(buf_size);
378
379        buffer.put_u8(PacketType::Fulfill as u8);
380        buffer.put_var_octet_string_length(content_len);
381        let content_offset = buffer.len();
382        buffer.put_slice(&self.fulfillment[..]);
383        buffer.put_var_octet_string(&self.data[..]);
384        Fulfill {
385            buffer,
386            content_offset,
387        }
388    }
389}
390
391#[derive(PartialEq, Clone)]
392pub struct Reject {
393    buffer: BytesMut,
394    code: ErrorCode,
395    message_offset: usize,
396    triggered_by_offset: usize,
397    data_offset: usize,
398}
399
400#[derive(Clone, Debug, PartialEq)]
401pub struct RejectBuilder<'a> {
402    pub code: ErrorCode,
403    pub message: &'a [u8],
404    pub triggered_by: Option<&'a Address>,
405    pub data: &'a [u8],
406}
407
408impl TryFrom<BytesMut> for Reject {
409    type Error = ParseError;
410
411    fn try_from(buffer: BytesMut) -> Result<Self, Self::Error> {
412        let (content_offset, mut content) = deserialize_envelope(PacketType::Reject, &buffer)?;
413        let content_len = content.len();
414
415        let mut code = [0; 3];
416        content.read_exact(&mut code)?;
417        let code = ErrorCode::new(code);
418
419        let triggered_by_offset = content_offset + content_len - content.len();
420        Address::try_from(content.read_var_octet_string()?)?;
421
422        let message_offset = content_offset + content_len - content.len();
423        content.skip_var_octet_string()?;
424
425        let data_offset = content_offset + content_len - content.len();
426        content.skip_var_octet_string()?;
427
428        Ok(Reject {
429            buffer,
430            code,
431            triggered_by_offset,
432            message_offset,
433            data_offset,
434        })
435    }
436}
437
438impl Reject {
439    #[inline]
440    pub fn code(&self) -> ErrorCode {
441        self.code
442    }
443
444    #[inline]
445    pub fn triggered_by(&self) -> Option<Address> {
446        match (&self.buffer[self.triggered_by_offset..]).peek_var_octet_string() {
447            Ok(bytes) => Address::try_from(bytes).ok(),
448            Err(_) => None,
449        }
450    }
451
452    #[inline]
453    pub fn message(&self) -> &[u8] {
454        (&self.buffer[self.message_offset..])
455            .peek_var_octet_string()
456            .unwrap()
457    }
458
459    #[inline]
460    pub fn data(&self) -> &[u8] {
461        (&self.buffer[self.data_offset..])
462            .peek_var_octet_string()
463            .unwrap()
464    }
465
466    pub fn into_data(mut self) -> BytesMut {
467        oer::extract_var_octet_string(self.buffer.split_off(self.data_offset)).unwrap()
468    }
469}
470
471impl AsRef<[u8]> for Reject {
472    #[inline]
473    fn as_ref(&self) -> &[u8] {
474        &self.buffer
475    }
476}
477
478impl From<Reject> for BytesMut {
479    fn from(reject: Reject) -> Self {
480        reject.buffer
481    }
482}
483
484impl fmt::Debug for Reject {
485    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
486        formatter
487            .debug_struct("Reject")
488            .field("code", &self.code())
489            .field(
490                "message",
491                &str::from_utf8(self.message()).map_err(|_| fmt::Error)?,
492            )
493            .field("triggered_by", &self.triggered_by())
494            .field("data_length", &self.data().len())
495            .finish()
496    }
497}
498
499impl<'a> RejectBuilder<'a> {
500    pub fn build(&self) -> Reject {
501        let (trigerred_by_message, len) = match self.triggered_by {
502            Some(ref msg) => (msg.as_ref(), msg.len()),
503            None => {
504                let empty_msg: &[u8] = &[];
505                (empty_msg, 0)
506            }
507        };
508        let triggered_by_size = oer::predict_var_octet_string(len);
509        let message_size = oer::predict_var_octet_string(self.message.len());
510        let data_size = oer::predict_var_octet_string(self.data.len());
511        let content_len = ERROR_CODE_LEN + triggered_by_size + message_size + data_size;
512        let buf_size = 1 + oer::predict_var_octet_string(content_len);
513        let mut buffer = BytesMut::with_capacity(buf_size);
514
515        buffer.put_u8(PacketType::Reject as u8);
516        buffer.put_var_octet_string_length(content_len);
517        buffer.put_slice(&<[u8; 3]>::from(self.code)[..]);
518        buffer.put_var_octet_string::<&[u8]>(trigerred_by_message);
519        buffer.put_var_octet_string(self.message);
520        buffer.put_var_octet_string(self.data);
521        Reject {
522            buffer,
523            code: self.code,
524            triggered_by_offset: buf_size - data_size - message_size - triggered_by_size,
525            message_offset: buf_size - data_size - message_size,
526            data_offset: buf_size - data_size,
527        }
528    }
529}
530
531fn deserialize_envelope(
532    packet_type: PacketType,
533    mut reader: &[u8],
534) -> Result<(usize, &[u8]), ParseError> {
535    let got_type = reader.read_u8()?;
536    if got_type == packet_type as u8 {
537        let content_offset = 1 + {
538            // This could probably be determined a better way...
539            let mut peek = &reader[..];
540            let before = peek.len();
541            peek.read_var_octet_string_length()?;
542            before - peek.len()
543        };
544        let content = reader.peek_var_octet_string()?;
545        Ok((content_offset, content))
546    } else {
547        Err(ParseError::InvalidPacket(format!(
548            "Unexpected packet type: {:?}",
549            got_type,
550        )))
551    }
552}
553
554#[derive(Clone, Debug, PartialEq)]
555pub struct MaxPacketAmountDetails {
556    amount_received: u64,
557    max_amount: u64,
558}
559
560impl MaxPacketAmountDetails {
561    #[inline]
562    pub fn new(amount_received: u64, max_amount: u64) -> Self {
563        MaxPacketAmountDetails {
564            amount_received,
565            max_amount,
566        }
567    }
568
569    // Convert to use TryFrom? Also probably should go to max_packet_amount.rs
570    pub fn from_bytes(mut bytes: &[u8]) -> Result<Self, std::io::Error> {
571        let amount_received = bytes.read_u64::<BigEndian>()?;
572        let max_amount = bytes.read_u64::<BigEndian>()?;
573        Ok(MaxPacketAmountDetails::new(amount_received, max_amount))
574    }
575
576    pub fn to_bytes(&self) -> [u8; 16] {
577        let mut bytes = [0x00_u8; 16];
578        let mut writer = Cursor::new(&mut bytes[..]);
579        writer.put_u64_be(self.amount_received);
580        writer.put_u64_be(self.max_amount);
581        bytes
582    }
583
584    #[inline]
585    pub fn amount_received(&self) -> u64 {
586        self.amount_received
587    }
588
589    #[inline]
590    pub fn max_amount(&self) -> u64 {
591        self.max_amount
592    }
593}
594
595#[cfg(test)]
596mod test_packet_type {
597    use super::*;
598
599    #[test]
600    fn test_try_from() {
601        assert_eq!(PacketType::try_from(12).unwrap(), PacketType::Prepare);
602        assert_eq!(PacketType::try_from(13).unwrap(), PacketType::Fulfill);
603        assert_eq!(PacketType::try_from(14).unwrap(), PacketType::Reject);
604        assert!(PacketType::try_from(15).is_err());
605    }
606}
607
608#[cfg(test)]
609mod test_packet {
610    use super::*;
611    use crate::fixtures::{FULFILL, PREPARE, REJECT};
612    use crate::fixtures::{FULFILL_BYTES, PREPARE_BYTES, REJECT_BYTES};
613
614    #[test]
615    fn test_try_from() {
616        assert_eq!(
617            Packet::try_from(BytesMut::from(PREPARE_BYTES)).unwrap(),
618            Packet::Prepare(PREPARE.clone()),
619        );
620        assert_eq!(
621            Packet::try_from(BytesMut::from(FULFILL_BYTES)).unwrap(),
622            Packet::Fulfill(FULFILL.clone()),
623        );
624        assert_eq!(
625            Packet::try_from(BytesMut::from(REJECT_BYTES)).unwrap(),
626            Packet::Reject(REJECT.clone()),
627        );
628
629        // Empty buffer:
630        assert!(Packet::try_from(BytesMut::from(vec![])).is_err());
631        // Unknown packet type:
632        assert!(Packet::try_from(BytesMut::from(vec![0x99])).is_err());
633    }
634
635    #[test]
636    fn test_into_bytes_mut() {
637        assert_eq!(
638            BytesMut::from(Packet::Prepare(PREPARE.clone())),
639            BytesMut::from(PREPARE_BYTES),
640        );
641        assert_eq!(
642            BytesMut::from(Packet::Fulfill(FULFILL.clone())),
643            BytesMut::from(FULFILL_BYTES),
644        );
645        assert_eq!(
646            BytesMut::from(Packet::Reject(REJECT.clone())),
647            BytesMut::from(REJECT_BYTES),
648        );
649    }
650}
651
652#[cfg(test)]
653mod test_prepare {
654    use super::*;
655    use crate::fixtures::{self, PREPARE, PREPARE_BUILDER, PREPARE_BYTES};
656
657    #[test]
658    fn test_invalid_address() {
659        let mut prep = BytesMut::from(PREPARE_BYTES);
660        prep[67] = 42; // convert a byte from the address to a junk character
661        assert!(Prepare::try_from(prep).is_err());
662    }
663
664    #[test]
665    fn test_try_from() {
666        assert_eq!(
667            Prepare::try_from(BytesMut::from(PREPARE_BYTES)).unwrap(),
668            *PREPARE
669        );
670
671        // Incorrect packet type on an otherwise well-formed Prepare.
672        assert!(Prepare::try_from({
673            let mut with_wrong_type = BytesMut::from(PREPARE_BYTES);
674            with_wrong_type[0] = PacketType::Fulfill as u8;
675            with_wrong_type
676        })
677        .is_err());
678
679        // A packet with junk data appened to the end.
680        let with_junk_data = Prepare::try_from({
681            let mut buffer = BytesMut::from(PREPARE_BYTES);
682            buffer.extend_from_slice(&[0x11, 0x12, 0x13]);
683            buffer
684        })
685        .unwrap();
686        assert_eq!(with_junk_data.amount(), PREPARE.amount());
687        assert_eq!(with_junk_data.expires_at(), *fixtures::EXPIRES_AT);
688        assert_eq!(
689            with_junk_data.execution_condition(),
690            fixtures::EXECUTION_CONDITION
691        );
692        assert_eq!(with_junk_data.destination(), PREPARE.destination());
693        assert_eq!(with_junk_data.data(), fixtures::DATA);
694    }
695
696    #[test]
697    fn test_into_bytes_mut() {
698        assert_eq!(BytesMut::from(PREPARE.clone()), PREPARE_BYTES);
699    }
700
701    #[test]
702    fn test_amount() {
703        assert_eq!(PREPARE.amount(), PREPARE_BUILDER.amount);
704    }
705
706    #[test]
707    fn test_set_amount() {
708        let target_amount = PREPARE_BUILDER.amount;
709        let destination = PREPARE_BUILDER.destination.clone();
710        let mut prepare = PrepareBuilder {
711            amount: 9999,
712            destination,
713            ..*PREPARE_BUILDER
714        }
715        .build();
716        prepare.set_amount(target_amount);
717        assert_eq!(prepare.amount(), target_amount);
718        assert_eq!(BytesMut::from(prepare), PREPARE_BYTES);
719    }
720
721    #[test]
722    fn test_expires_at() {
723        assert_eq!(PREPARE.expires_at(), *fixtures::EXPIRES_AT);
724    }
725
726    #[test]
727    fn test_set_expires_at() {
728        let target_expiry = PREPARE_BUILDER.expires_at;
729        let destination = PREPARE_BUILDER.destination.clone();
730        let mut prepare = PrepareBuilder {
731            expires_at: SystemTime::now(),
732            destination,
733            ..*PREPARE_BUILDER
734        }
735        .build();
736        prepare.set_expires_at(target_expiry);
737        assert_eq!(prepare.expires_at(), target_expiry);
738        assert_eq!(BytesMut::from(prepare), PREPARE_BYTES);
739    }
740
741    #[test]
742    fn test_execution_condition() {
743        assert_eq!(PREPARE.execution_condition(), fixtures::EXECUTION_CONDITION,);
744    }
745
746    #[test]
747    fn test_data() {
748        assert_eq!(PREPARE.data(), fixtures::DATA);
749    }
750
751    #[test]
752    fn test_into_data() {
753        assert_eq!(PREPARE.clone().into_data(), BytesMut::from(PREPARE.data()),);
754    }
755}
756
757#[cfg(test)]
758mod test_fulfill {
759    use super::*;
760    use crate::fixtures::{self, FULFILL, FULFILL_BYTES};
761
762    #[test]
763    fn test_try_from() {
764        assert_eq!(
765            Fulfill::try_from(BytesMut::from(FULFILL_BYTES)).unwrap(),
766            *FULFILL
767        );
768
769        // A packet with junk data appened to the end.
770        let with_junk_data = Fulfill::try_from({
771            let mut buffer = BytesMut::from(FULFILL_BYTES);
772            buffer.extend_from_slice(&[0x11, 0x12, 0x13]);
773            buffer
774        })
775        .unwrap();
776        assert_eq!(with_junk_data.fulfillment(), fixtures::FULFILLMENT);
777        assert_eq!(with_junk_data.data(), fixtures::DATA);
778
779        // Fail to parse a packet missing a data field, even if a VarStr is in
780        // the junk data.
781        let with_data_in_junk = {
782            let mut buffer = BytesMut::with_capacity(1024);
783            buffer.put_u8(PacketType::Fulfill as u8);
784            buffer.put_var_octet_string_length(32);
785            buffer.put_slice(&fixtures::FULFILLMENT[..]);
786            buffer.put_var_octet_string(fixtures::DATA);
787            buffer
788        };
789        assert!(Fulfill::try_from(with_data_in_junk).is_err());
790    }
791
792    #[test]
793    fn test_into_bytes_mut() {
794        assert_eq!(BytesMut::from(FULFILL.clone()), FULFILL_BYTES);
795    }
796
797    #[test]
798    fn test_fulfillment() {
799        assert_eq!(FULFILL.fulfillment(), fixtures::FULFILLMENT);
800    }
801
802    #[test]
803    fn test_data() {
804        assert_eq!(FULFILL.data(), fixtures::DATA);
805    }
806
807    #[test]
808    fn test_into_data() {
809        assert_eq!(FULFILL.clone().into_data(), BytesMut::from(FULFILL.data()),);
810    }
811}
812
813#[cfg(test)]
814mod test_reject {
815    use super::*;
816    use crate::fixtures::{self, REJECT, REJECT_BUILDER, REJECT_BYTES};
817
818    #[test]
819    fn test_try_from() {
820        assert_eq!(
821            Reject::try_from(BytesMut::from(REJECT_BYTES)).unwrap(),
822            *REJECT,
823        );
824
825        // A packet with junk data appened to the end.
826        let with_junk_data = Reject::try_from({
827            let mut buffer = BytesMut::from(REJECT_BYTES);
828            buffer.extend_from_slice(&[0x11, 0x12, 0x13]);
829            buffer
830        })
831        .unwrap();
832        assert_eq!(with_junk_data.code(), REJECT_BUILDER.code);
833        assert_eq!(with_junk_data.message(), REJECT_BUILDER.message);
834        assert_eq!(
835            with_junk_data.triggered_by().as_ref(),
836            REJECT_BUILDER.triggered_by
837        );
838        assert_eq!(with_junk_data.data(), fixtures::DATA);
839    }
840
841    #[test]
842    fn test_into_bytes_mut() {
843        assert_eq!(BytesMut::from(REJECT.clone()), REJECT_BYTES);
844    }
845
846    #[test]
847    fn test_code() {
848        assert_eq!(REJECT.code(), REJECT_BUILDER.code);
849    }
850
851    #[test]
852    fn test_message() {
853        assert_eq!(REJECT.message(), REJECT_BUILDER.message);
854    }
855
856    #[test]
857    fn test_triggered_by() {
858        assert_eq!(REJECT.triggered_by().as_ref(), REJECT_BUILDER.triggered_by);
859    }
860
861    #[test]
862    fn test_data() {
863        assert_eq!(REJECT.data(), fixtures::DATA);
864    }
865
866    #[test]
867    fn test_into_data() {
868        assert_eq!(REJECT.clone().into_data(), BytesMut::from(REJECT.data()));
869    }
870}
871
872#[cfg(test)]
873mod test_max_packet_amount_details {
874    use super::*;
875
876    static BYTES: &[u8] = b"\
877        \x00\x00\x00\x00\x00\x03\x02\x01\
878        \x00\x00\x00\x00\x00\x06\x05\x04\
879    ";
880
881    static DETAILS: MaxPacketAmountDetails = MaxPacketAmountDetails {
882        amount_received: 0x0003_0201,
883        max_amount: 0x0006_0504,
884    };
885
886    #[test]
887    fn test_from_bytes() {
888        assert_eq!(MaxPacketAmountDetails::from_bytes(&BYTES).unwrap(), DETAILS,);
889        assert_eq!(
890            MaxPacketAmountDetails::from_bytes(&[][..])
891                .unwrap_err()
892                .kind(),
893            std::io::ErrorKind::UnexpectedEof,
894        );
895    }
896
897    #[test]
898    fn test_to_bytes() {
899        assert_eq!(&DETAILS.to_bytes()[..], BYTES);
900    }
901
902    #[test]
903    fn test_amount_received() {
904        assert_eq!(DETAILS.amount_received(), 0x0003_0201);
905    }
906
907    #[test]
908    fn test_max_amount() {
909        assert_eq!(DETAILS.max_amount(), 0x0006_0504);
910    }
911}