18
18
//! extern crate core;
19
19
//! extern crate lightning;
20
20
//!
21
+ //! use core::convert::TryFrom;
21
22
//! use core::num::NonZeroU64;
22
23
//! use core::time::Duration;
23
24
//!
24
25
//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
25
26
//! use lightning::offers::offer::{Amount, Offer, OfferBuilder};
26
27
//! use lightning::offers::parse::ParseError;
28
+ //! use lightning::util::ser::{Readable, Writeable};
27
29
//!
28
30
//! # use lightning::onion_message::BlindedPath;
29
31
//! # #[cfg(feature = "std")]
54
56
//!
55
57
//! // Parse from a bech32 string after scanning from a QR code.
56
58
//! let offer = encoded_offer.parse::<Offer>()?;
59
+ //!
60
+ //! // Encode offer as raw bytes.
61
+ //! let mut bytes = Vec::new();
62
+ //! offer.write(&mut bytes).unwrap();
63
+ //!
64
+ //! // Decode raw bytes into an offer.
65
+ //! let offer = Offer::try_from(bytes)?;
57
66
//! # Ok(())
58
67
//! # }
59
68
//! ```
@@ -71,7 +80,7 @@ use ln::features::OfferFeatures;
71
80
use ln:: msgs:: MAX_VALUE_MSAT ;
72
81
use offers:: parse:: { Bech32Encode , ParseError , SemanticError } ;
73
82
use onion_message:: BlindedPath ;
74
- use util:: ser:: { HighZeroBytesDroppedBigSize , WithoutLength , Writeable , Writer } ;
83
+ use util:: ser:: { HighZeroBytesDroppedBigSize , Readable , WithoutLength , Writeable , Writer } ;
75
84
76
85
use prelude:: * ;
77
86
@@ -408,12 +417,27 @@ impl OfferContents {
408
417
}
409
418
}
410
419
420
+ impl Writeable for Offer {
421
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
422
+ WithoutLength ( & self . bytes ) . write ( writer)
423
+ }
424
+ }
425
+
411
426
impl Writeable for OfferContents {
412
427
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
413
428
self . as_tlv_stream ( ) . write ( writer)
414
429
}
415
430
}
416
431
432
+ impl TryFrom < Vec < u8 > > for Offer {
433
+ type Error = ParseError ;
434
+
435
+ fn try_from ( bytes : Vec < u8 > ) -> Result < Self , Self :: Error > {
436
+ let tlv_stream: OfferTlvStream = Readable :: read ( & mut & bytes[ ..] ) ?;
437
+ Offer :: try_from ( ( bytes, tlv_stream) )
438
+ }
439
+ }
440
+
417
441
/// The minimum amount required for an item in an [`Offer`], denominated in either bitcoin or
418
442
/// another currency.
419
443
#[ derive( Clone , Debug , PartialEq ) ]
@@ -466,6 +490,8 @@ impl Bech32Encode for Offer {
466
490
const BECH32_HRP : & ' static str = "lno" ;
467
491
}
468
492
493
+ type ParsedOffer = ( Vec < u8 > , OfferTlvStream ) ;
494
+
469
495
impl FromStr for Offer {
470
496
type Err = ParseError ;
471
497
@@ -476,6 +502,16 @@ impl FromStr for Offer {
476
502
}
477
503
}
478
504
505
+ impl TryFrom < ParsedOffer > for Offer {
506
+ type Error = ParseError ;
507
+
508
+ fn try_from ( offer : ParsedOffer ) -> Result < Self , Self :: Error > {
509
+ let ( bytes, tlv_stream) = offer;
510
+ let contents = OfferContents :: try_from ( tlv_stream) ?;
511
+ Ok ( Offer { bytes, contents } )
512
+ }
513
+ }
514
+
479
515
impl TryFrom < OfferTlvStream > for OfferContents {
480
516
type Error = SemanticError ;
481
517
@@ -544,11 +580,12 @@ impl core::fmt::Display for Offer {
544
580
545
581
#[ cfg( test) ]
546
582
mod tests {
547
- use super :: { Amount , OfferBuilder } ;
583
+ use super :: { Amount , Offer , OfferBuilder } ;
548
584
549
585
use bitcoin:: blockdata:: constants:: ChainHash ;
550
586
use bitcoin:: network:: constants:: Network ;
551
587
use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
588
+ use core:: convert:: TryFrom ;
552
589
use core:: num:: NonZeroU64 ;
553
590
use core:: time:: Duration ;
554
591
use ln:: features:: OfferFeatures ;
@@ -571,7 +608,7 @@ mod tests {
571
608
let offer = OfferBuilder :: new ( "foo" . into ( ) , pubkey ( 42 ) ) . build ( ) . unwrap ( ) ;
572
609
let tlv_stream = offer. as_tlv_stream ( ) ;
573
610
let mut buffer = Vec :: new ( ) ;
574
- offer. contents . write ( & mut buffer) . unwrap ( ) ;
611
+ offer. write ( & mut buffer) . unwrap ( ) ;
575
612
576
613
assert_eq ! ( offer. bytes, buffer. as_slice( ) ) ;
577
614
assert_eq ! ( offer. chains( ) , vec![ ChainHash :: using_genesis_block( Network :: Bitcoin ) ] ) ;
@@ -600,6 +637,10 @@ mod tests {
600
637
assert_eq ! ( tlv_stream. quantity_min, None ) ;
601
638
assert_eq ! ( tlv_stream. quantity_max, None ) ;
602
639
assert_eq ! ( tlv_stream. node_id, Some ( & pubkey( 42 ) ) ) ;
640
+
641
+ if let Err ( e) = Offer :: try_from ( buffer) {
642
+ panic ! ( "error parsing offer: {:?}" , e) ;
643
+ }
603
644
}
604
645
605
646
#[ test]
0 commit comments