Skip to content

Commit 256d821

Browse files
committed
descriptors: allow whitespace in string parsing. Improve error type
1 parent c2554cf commit 256d821

2 files changed

Lines changed: 34 additions & 15 deletions

File tree

descriptors/src/compiler/compile.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,10 @@ where K::Err: core::error::Error
443443
////////////////////////////////////////
444444
// Combinators
445445

446+
fn trim_start_expr<'s>(s: &'s str, expr: &'static str) -> Option<&'s str> {
447+
s.trim_start().strip_prefix(expr).and_then(|rest| rest.trim_start().strip_prefix("("))
448+
}
449+
446450
impl<K: DeriveSet + Display + FromStr> FromStr for Sh<K>
447451
where
448452
K::Err: core::error::Error,
@@ -452,11 +456,14 @@ where
452456
type Err = DescrParseError<K::Err>;
453457

454458
fn from_str(s: &str) -> Result<Self, Self::Err> {
455-
if s.starts_with("sh(wsh(") {
459+
let Some(rest) = trim_start_expr(s, "sh") else {
460+
return Err(DescrParseError::NoRequiredScript("sh"));
461+
};
462+
if rest.starts_with("wsh") {
456463
Ok(ShWsh::from_str(s)?.into())
457-
} else if s.starts_with("sh(sortedmulti(") {
464+
} else if rest.starts_with("sortedmulti") {
458465
ShSortedMulti::from_str(s).map(Sh::ShSortedMulti)
459-
} else if s.starts_with("sh(multi(") {
466+
} else if rest.starts_with("multi") {
460467
ShMulti::from_str(s).map(Sh::ShMulti)
461468
} else {
462469
ShScript::from_str(s).map(Sh::ShScript)
@@ -470,9 +477,13 @@ where K::Err: core::error::Error
470477
type Err = DescrParseError<K::Err>;
471478

472479
fn from_str(s: &str) -> Result<Self, Self::Err> {
473-
if s.starts_with("wsh(multi(") {
480+
let Some(rest) = trim_start_expr(s, "wsh") else {
481+
return Err(DescrParseError::NoRequiredScript("wsh"));
482+
};
483+
let rest = rest.trim_start();
484+
if rest.starts_with("multi") {
474485
WshMulti::from_str(s).map(Wsh::Multi)
475-
} else if s.starts_with("wsh(sortedmulti(") {
486+
} else if rest.starts_with("sortedmulti") {
476487
WshSortedMulti::from_str(s).map(Wsh::SortedMulti)
477488
} else {
478489
WshScript::from_str(s).map(Wsh::Script)
@@ -486,14 +497,18 @@ where K::Err: core::error::Error
486497
type Err = DescrParseError<K::Err>;
487498

488499
fn from_str(s: &str) -> Result<Self, Self::Err> {
489-
if s.starts_with("sh(wsh(multi(") {
500+
let Some(rest) = trim_start_expr(s, "sh") else {
501+
return Err(DescrParseError::NoRequiredScript("sh"));
502+
};
503+
let Some(rest) = trim_start_expr(rest, "wsh") else {
504+
return Err(DescrParseError::NoRequiredScript("wsh"));
505+
};
506+
if rest.starts_with("multi") {
490507
ShWshMulti::from_str(s).map(ShWsh::Multi)
491-
} else if s.starts_with("sh(wsh(sortedmulti(") {
508+
} else if rest.starts_with("sortedmulti") {
492509
ShWshSortedMulti::from_str(s).map(ShWsh::SortedMulti)
493-
} else if s.starts_with("sh(wsh(") {
494-
ShWshScript::from_str(s).map(ShWsh::Script)
495510
} else {
496-
Err(DescrParseError::InvalidScriptExpr(s.to_owned()))
511+
ShWshScript::from_str(s).map(ShWsh::Script)
497512
}
498513
}
499514
}
@@ -526,7 +541,7 @@ where
526541
type Err = DescrParseError<K::Err>;
527542

528543
fn from_str(s: &str) -> Result<Self, Self::Err> {
529-
Ok(match s {
544+
Ok(match s.trim_start() {
530545
s if s.starts_with("pkh") => Self::Pkh(Pkh::from_str(s)?),
531546
s if s.starts_with("wpkh") => Self::Wpkh(Wpkh::from_str(s)?),
532547

descriptors/src/compiler/parser.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub enum DescrParseError<E: Error> {
5454
/// script expression '{0}' must have a name.
5555
NoName(String),
5656

57+
/// the descriptor must start with '{0}' script expression.
58+
NoRequiredScript(&'static str),
59+
5760
/// unexpected token '{token}' when {expected} is expected.
5861
UnexpectedToken {
5962
descr: String,
@@ -75,10 +78,10 @@ pub enum DescrParseError<E: Error> {
7578
/// invalid descriptor tree expression '{0}'.
7679
InvalidTreeExpr(String),
7780

78-
/// invalid key expression: {0}.
79-
Key(E),
81+
/// invalid {0} expression. {1}
82+
Expr(&'static str, E),
8083

81-
/// invalid number literal: {0}.
84+
/// invalid number literal. {0}
8285
#[from]
8386
Lit(ParseIntError),
8487

@@ -100,6 +103,7 @@ impl<E1: Error> DescrParseError<E1> {
100103
DescrParseError::Empty => Self::Empty,
101104
DescrParseError::Lexer(err) => Self::Lexer(err),
102105
DescrParseError::NoName(s) => Self::NoName(s),
106+
DescrParseError::NoRequiredScript(s) => Self::NoRequiredScript(s),
103107
DescrParseError::UnexpectedToken {
104108
descr,
105109
pos,
@@ -122,7 +126,7 @@ impl<E1: Error> DescrParseError<E1> {
122126
},
123127
DescrParseError::InvalidScriptExpr(s) => Self::InvalidScriptExpr(s),
124128
DescrParseError::InvalidTreeExpr(s) => Self::InvalidTreeExpr(s),
125-
DescrParseError::Key(err) => Self::Key(err.into()),
129+
DescrParseError::Expr(msg, err) => Self::Expr(msg, err.into()),
126130
DescrParseError::Lit(err) => Self::Lit(err),
127131
DescrParseError::Confinement(err) => Self::Confinement(err),
128132
DescrParseError::InvalidArgs(s) => Self::InvalidArgs(s),

0 commit comments

Comments
 (0)