1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! `bcur` — a Rust implementation of [Uniform Resources](https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md).
//!
//! # Features
//!
//! - **`std`** (default): host builds.
//! - **`dcbor`**: typed [`typed::Ur`] and [`UrEncodable`] / [`UrDecodable`]
//! (implies `std`).
//!
//! Core transport always requires `alloc` and supports `no_std` via
//! `--no-default-features`.
//!
//! # Layering
//!
//! **L0–L3 (always built).** A UR type token is a validated label
//! (`[a-z0-9-]+` after ASCII lowercasing). The body is raw bytes plus
//! bytewords CRC. [`ur::encode`] / [`ur::Encoder`] do **not** parse or
//! require CBOR, so generic hosts and tests can move opaque payloads; this
//! split matches ur-rs.
//!
//! **BCR-2020-005** says a UR *message* MUST be dCBOR and that type
//! `bytes` MUST NOT be used except for testing. That MUST is enforced on
//! **L4** (`feature = "dcbor"`): `FromStr for typed::Ur` and
//! `TryFrom<ur::Decoded> for typed::Ur` reject non-dCBOR
//! ([`ErrorKind::CborDecode`]).
//! L4 also uses the first registered `dcbor` tag **name** as the type
//! token and strips the tag from the UR body (005 "top-level UR is
//! untagged").
//!
//! Registry types (seed, hdkey, PSBT, …) are not part of this crate;
//! application types implement [`UrEncodable`] / [`UrDecodable`].
//!
//! # Example
//!
//! L3 transport (opaque bytes + type token):
//!
//! ```
//! use bcur::fountain::EncoderOptions;
//! use bcur::ur::{Decoder, Encoder};
//! use bcur::{State, UrType};
//!
//! let data = b"Ten chars!".repeat(10);
//! let mut encoder =
//! Encoder::new(UrType::new("alpha").unwrap(), data.clone(), EncoderOptions::new(10)).unwrap();
//! let mut decoder = Decoder::default();
//! for frame in encoder.by_ref() {
//! decoder.receive(&frame).unwrap();
//! if matches!(decoder.state(), State::Complete(_)) {
//! break;
//! }
//! }
//! assert_eq!(decoder.into_decoded().unwrap().message(), data.as_slice());
//! ```
//!
//! Typed dCBOR (`feature = "dcbor"`):
//!
//! ```
//! # #[cfg(feature = "dcbor")]
//! # {
//! use bcur::{Ur, ur_type};
//! let ur = Ur::new(ur_type!("test"), vec![1, 2, 3]);
//! assert_eq!(ur.to_string(), "ur:test/lsadaoaxjygonesw");
//! # }
//! ```
extern crate alloc;
pub use Style;
pub use ;
pub use ;
pub use UrType;
// Dev-only tools are linked into test/bench targets; keep the lib lint clean.
use criterion as _;
use serde_json as _;
pub use ;