Skip to content

Commit ef3a73c

Browse files
committed
Merge rust-bitcoin/rust-bitcoin#1137: Impl string conversion traits for CommandString
405be52 Impl string conversion traits for `CommandString` (Martin Habovstiak) Pull request description: After MSRV bump `try_from` usually refers to `TryFrom` method but `CommandString` used inherent one making it confusing and non-idiomatic. This implements `FromStr` and `TryFrom<{stringly type}>` for `CommandString` and deprecates the inherent method in favor of those. To keep the code using `&'static str` efficient it provides `try_from_static` inherent method that only converts from `&'static str`. Closes #1135 ACKs for top commit: sanket1729: utACK 405be52 tcharding: ACK 405be52 Tree-SHA512: 754fc960a4bc5c096cccf47b85a620e33fcf863f3c57ea113eae91cd34006168113dd1efc47231e79e6e237e2fc412890cc9e8a72d4cfc633bfebbecdc4610e6
2 parents f6624f3 + af69d27 commit ef3a73c

File tree

1 file changed

+55
-5
lines changed

1 file changed

+55
-5
lines changed

src/network/message.rs

+55-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use crate::prelude::*;
1111

1212
use core::{fmt, iter};
13+
use core::convert::TryFrom;
1314

1415
use crate::io;
1516
use io::Read as _;
@@ -46,8 +47,25 @@ impl CommandString {
4647
///
4748
/// Returns an error if and only if the string is
4849
/// larger than 12 characters in length.
50+
#[deprecated(note = "Use `TryFrom::try_from` or `CommandString::try_from_static`", since = "0.29.0")]
4951
pub fn try_from<S: Into<Cow<'static, str>>>(s: S) -> Result<CommandString, CommandStringError> {
50-
let cow = s.into();
52+
Self::try_from_static_cow(s.into())
53+
}
54+
55+
/// Convert `&'static str` to `CommandString`
56+
///
57+
/// This is more efficient for string literals than non-static conversions because it avoids
58+
/// allocation.
59+
///
60+
/// # Errors
61+
///
62+
/// Returns an error if and only if the string is
63+
/// larger than 12 characters in length.
64+
pub fn try_from_static(s: &'static str) -> Result<CommandString, CommandStringError> {
65+
Self::try_from_static_cow(s.into())
66+
}
67+
68+
fn try_from_static_cow(cow: Cow<'static, str>) -> Result<CommandString, CommandStringError> {
5169
if cow.len() > 12 {
5270
Err(CommandStringError { cow })
5371
} else {
@@ -56,6 +74,38 @@ impl CommandString {
5674
}
5775
}
5876

77+
impl TryFrom<String> for CommandString {
78+
type Error = CommandStringError;
79+
80+
fn try_from(value: String) -> Result<Self, Self::Error> {
81+
Self::try_from_static_cow(value.into())
82+
}
83+
}
84+
85+
impl TryFrom<Box<str>> for CommandString {
86+
type Error = CommandStringError;
87+
88+
fn try_from(value: Box<str>) -> Result<Self, Self::Error> {
89+
Self::try_from_static_cow(String::from(value).into())
90+
}
91+
}
92+
93+
impl<'a> TryFrom<&'a str> for CommandString {
94+
type Error = CommandStringError;
95+
96+
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
97+
Self::try_from_static_cow(value.to_owned().into())
98+
}
99+
}
100+
101+
impl core::str::FromStr for CommandString {
102+
type Err = CommandStringError;
103+
104+
fn from_str(s: &str) -> Result<Self, Self::Err> {
105+
Self::try_from_static_cow(s.to_owned().into())
106+
}
107+
}
108+
59109
impl fmt::Display for CommandString {
60110
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61111
f.write_str(self.0.as_ref())
@@ -264,7 +314,7 @@ impl NetworkMessage {
264314
pub fn command(&self) -> CommandString {
265315
match *self {
266316
NetworkMessage::Unknown { command: ref c, .. } => c.clone(),
267-
_ => CommandString::try_from(self.cmd()).expect("cmd returns valid commands")
317+
_ => CommandString::try_from_static(self.cmd()).expect("cmd returns valid commands")
268318
}
269319
}
270320
}
@@ -523,8 +573,8 @@ mod test {
523573
#[test]
524574
fn commandstring_test() {
525575
// Test converting.
526-
assert_eq!(CommandString::try_from("AndrewAndrew").unwrap().as_ref(), "AndrewAndrew");
527-
assert!(CommandString::try_from("AndrewAndrewA").is_err());
576+
assert_eq!(CommandString::try_from_static("AndrewAndrew").unwrap().as_ref(), "AndrewAndrew");
577+
assert!(CommandString::try_from_static("AndrewAndrewA").is_err());
528578

529579
// Test serializing.
530580
let cs = CommandString("Andrew".into());
@@ -534,7 +584,7 @@ mod test {
534584
let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
535585
assert!(cs.is_ok());
536586
assert_eq!(cs.as_ref().unwrap().to_string(), "Andrew".to_owned());
537-
assert_eq!(cs.unwrap(), CommandString::try_from("Andrew").unwrap());
587+
assert_eq!(cs.unwrap(), CommandString::try_from_static("Andrew").unwrap());
538588

539589
let short_cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
540590
assert!(short_cs.is_err());

0 commit comments

Comments
 (0)