1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-09-05 18:41:00 +00:00

Merge branch 'oh-strings' into 'next'

Minor string optimizations

See merge request famedly/conduit!777
This commit is contained in:
Ossi Herrala 2025-08-26 14:15:57 +00:00
commit cc720e3343
19 changed files with 50 additions and 48 deletions

View file

@ -1,4 +1,4 @@
use crate::{services, utils, Error, Result, SUPPORTED_VERSIONS}; use crate::{services, Error, Result, SUPPORTED_VERSIONS};
use bytes::BytesMut; use bytes::BytesMut;
use ruma::api::{appservice::Registration, IncomingResponse, OutgoingRequest, SendAccessToken}; use ruma::api::{appservice::Registration, IncomingResponse, OutgoingRequest, SendAccessToken};
use std::{fmt::Debug, mem, time::Duration}; use std::{fmt::Debug, mem, time::Duration};
@ -92,7 +92,7 @@ where
destination, destination,
status, status,
url, url,
utils::string_from_bytes(&body) str::from_utf8(&body)
); );
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
service::{pdu::PduBuilder, rooms::timeline::PduCount}, service::{pdu::PduBuilder, rooms::timeline::PduCount},
services, utils, Error, Result, Ruma, services, Error, Result, Ruma,
}; };
use ruma::{ use ruma::{
api::client::{ api::client::{
@ -63,7 +63,7 @@ pub async fn send_message_event_route(
)); ));
} }
let event_id = utils::string_from_bytes(&response) let event_id = str::from_utf8(&response)
.map_err(|_| Error::bad_database("Invalid txnid bytes in database."))? .map_err(|_| Error::bad_database("Invalid txnid bytes in database."))?
.try_into() .try_into()
.map_err(|_| Error::bad_database("Invalid event id in txnid data."))?; .map_err(|_| Error::bad_database("Invalid event id in txnid data."))?;

View file

@ -7,7 +7,7 @@ use ruma::{
RoomId, UserId, RoomId, UserId,
}; };
use crate::{database::KeyValueDatabase, service, services, utils, Error, Result}; use crate::{database::KeyValueDatabase, service, services, Error, Result};
impl service::account_data::Data for KeyValueDatabase { impl service::account_data::Data for KeyValueDatabase {
/// Places one event in the account data of the user and removes the previous entry. /// Places one event in the account data of the user and removes the previous entry.
@ -147,9 +147,9 @@ impl KeyValueDatabase {
.map(|(k, v)| { .map(|(k, v)| {
Ok::<_, Error>(( Ok::<_, Error>((
RoomAccountDataEventType::from( RoomAccountDataEventType::from(
utils::string_from_bytes(k.rsplit(|&b| b == 0xff).next().ok_or_else( str::from_utf8(k.rsplit(|&b| b == 0xff).next().ok_or_else(|| {
|| Error::bad_database("RoomUserData ID in db is invalid."), Error::bad_database("RoomUserData ID in db is invalid.")
)?) })?)
.map_err(|_| Error::bad_database("RoomUserData ID in db is invalid."))?, .map_err(|_| Error::bad_database("RoomUserData ID in db is invalid."))?,
), ),
serde_json::from_slice::<Raw<T>>(&v).map_err(|_| { serde_json::from_slice::<Raw<T>>(&v).map_err(|_| {

View file

@ -221,7 +221,7 @@ impl service::key_backups::Data for KeyValueDatabase {
})?; })?;
let room_id = RoomId::parse( let room_id = RoomId::parse(
utils::string_from_bytes(parts.next().ok_or_else(|| { str::from_utf8(parts.next().ok_or_else(|| {
Error::bad_database("backupkeyid_backup key is invalid.") Error::bad_database("backupkeyid_backup key is invalid.")
})?) })?)
.map_err(|_| Error::bad_database("backupkeyid_backup room_id is invalid."))?, .map_err(|_| Error::bad_database("backupkeyid_backup room_id is invalid."))?,

View file

@ -3,7 +3,7 @@ use ruma::{
UserId, UserId,
}; };
use crate::{database::KeyValueDatabase, service, services, utils, Error, Result}; use crate::{database::KeyValueDatabase, service, services, Error, Result};
impl service::rooms::alias::Data for KeyValueDatabase { impl service::rooms::alias::Data for KeyValueDatabase {
fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId, user_id: &UserId) -> Result<()> { fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId, user_id: &UserId) -> Result<()> {
@ -41,7 +41,7 @@ impl service::rooms::alias::Data for KeyValueDatabase {
self.alias_roomid self.alias_roomid
.get(alias.alias().as_bytes())? .get(alias.alias().as_bytes())?
.map(|bytes| { .map(|bytes| {
RoomId::parse(utils::string_from_bytes(&bytes).map_err(|_| { RoomId::parse(str::from_utf8(&bytes).map_err(|_| {
Error::bad_database("Room ID in alias_roomid is invalid unicode.") Error::bad_database("Room ID in alias_roomid is invalid unicode.")
})?) })?)
.map_err(|_| Error::bad_database("Room ID in alias_roomid is invalid.")) .map_err(|_| Error::bad_database("Room ID in alias_roomid is invalid."))
@ -57,7 +57,7 @@ impl service::rooms::alias::Data for KeyValueDatabase {
prefix.push(0xff); prefix.push(0xff);
Box::new(self.aliasid_alias.scan_prefix(prefix).map(|(_, bytes)| { Box::new(self.aliasid_alias.scan_prefix(prefix).map(|(_, bytes)| {
utils::string_from_bytes(&bytes) str::from_utf8(&bytes)
.map_err(|_| Error::bad_database("Invalid alias bytes in aliasid_alias."))? .map_err(|_| Error::bad_database("Invalid alias bytes in aliasid_alias."))?
.try_into() .try_into()
.map_err(|_| Error::bad_database("Invalid alias in aliasid_alias.")) .map_err(|_| Error::bad_database("Invalid alias in aliasid_alias."))
@ -68,7 +68,7 @@ impl service::rooms::alias::Data for KeyValueDatabase {
self.alias_userid self.alias_userid
.get(alias.alias().as_bytes())? .get(alias.alias().as_bytes())?
.map(|bytes| { .map(|bytes| {
UserId::parse(utils::string_from_bytes(&bytes).map_err(|_| { UserId::parse(str::from_utf8(&bytes).map_err(|_| {
Error::bad_database("User ID in alias_userid is invalid unicode.") Error::bad_database("User ID in alias_userid is invalid unicode.")
})?) })?)
.map_err(|_| Error::bad_database("User ID in alias_roomid is invalid.")) .map_err(|_| Error::bad_database("User ID in alias_roomid is invalid."))

View file

@ -1,6 +1,6 @@
use ruma::{OwnedRoomId, RoomId}; use ruma::{OwnedRoomId, RoomId};
use crate::{database::KeyValueDatabase, service, utils, Error, Result}; use crate::{database::KeyValueDatabase, service, Error, Result};
impl service::rooms::directory::Data for KeyValueDatabase { impl service::rooms::directory::Data for KeyValueDatabase {
fn set_public(&self, room_id: &RoomId) -> Result<()> { fn set_public(&self, room_id: &RoomId) -> Result<()> {
@ -18,7 +18,7 @@ impl service::rooms::directory::Data for KeyValueDatabase {
fn public_rooms<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> { fn public_rooms<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
Box::new(self.publicroomids.iter().map(|(bytes, _)| { Box::new(self.publicroomids.iter().map(|(bytes, _)| {
RoomId::parse( RoomId::parse(
utils::string_from_bytes(&bytes).map_err(|_| { str::from_utf8(&bytes).map_err(|_| {
Error::bad_database("Room ID in publicroomids is invalid unicode.") Error::bad_database("Room ID in publicroomids is invalid unicode.")
})?, })?,
) )

View file

@ -92,7 +92,7 @@ impl service::rooms::edus::presence::Data for KeyValueDatabase {
.take_while(|(key, _)| key.starts_with(&prefix)) .take_while(|(key, _)| key.starts_with(&prefix))
{ {
let user_id = UserId::parse( let user_id = UserId::parse(
utils::string_from_bytes( str::from_utf8(
key.rsplit(|&b| b == 0xff) key.rsplit(|&b| b == 0xff)
.next() .next()
.expect("rsplit always returns an element"), .expect("rsplit always returns an element"),

View file

@ -77,7 +77,7 @@ impl service::rooms::edus::read_receipt::Data for KeyValueDatabase {
Error::bad_database("Invalid readreceiptid count in db.") Error::bad_database("Invalid readreceiptid count in db.")
})?; })?;
let user_id = UserId::parse( let user_id = UserId::parse(
utils::string_from_bytes(&k[prefix.len() + size_of::<u64>() + 1..]) str::from_utf8(&k[prefix.len() + size_of::<u64>() + 1..])
.map_err(|_| { .map_err(|_| {
Error::bad_database("Invalid readreceiptid userid bytes in db.") Error::bad_database("Invalid readreceiptid userid bytes in db.")
})?, })?,

View file

@ -1,6 +1,6 @@
use ruma::{OwnedRoomId, RoomId}; use ruma::{OwnedRoomId, RoomId};
use crate::{database::KeyValueDatabase, service, services, utils, Error, Result}; use crate::{database::KeyValueDatabase, service, services, Error, Result};
impl service::rooms::metadata::Data for KeyValueDatabase { impl service::rooms::metadata::Data for KeyValueDatabase {
fn exists(&self, room_id: &RoomId) -> Result<bool> { fn exists(&self, room_id: &RoomId) -> Result<bool> {
@ -21,7 +21,7 @@ impl service::rooms::metadata::Data for KeyValueDatabase {
fn iter_ids<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> { fn iter_ids<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
Box::new(self.roomid_shortroomid.iter().map(|(bytes, _)| { Box::new(self.roomid_shortroomid.iter().map(|(bytes, _)| {
RoomId::parse( RoomId::parse(
utils::string_from_bytes(&bytes).map_err(|_| { str::from_utf8(&bytes).map_err(|_| {
Error::bad_database("Room ID in publicroomids is invalid unicode.") Error::bad_database("Room ID in publicroomids is invalid unicode.")
})?, })?,
) )

View file

@ -122,7 +122,7 @@ impl service::rooms::short::Data for KeyValueDatabase {
.get(&shorteventid.to_be_bytes())? .get(&shorteventid.to_be_bytes())?
.ok_or_else(|| Error::bad_database("Shorteventid does not exist"))?; .ok_or_else(|| Error::bad_database("Shorteventid does not exist"))?;
let event_id = EventId::parse_arc(utils::string_from_bytes(&bytes).map_err(|_| { let event_id = EventId::parse_arc(str::from_utf8(&bytes).map_err(|_| {
Error::bad_database("EventID in shorteventid_eventid is invalid unicode.") Error::bad_database("EventID in shorteventid_eventid is invalid unicode.")
})?) })?)
.map_err(|_| Error::bad_database("EventId in shorteventid_eventid is invalid."))?; .map_err(|_| Error::bad_database("EventId in shorteventid_eventid is invalid."))?;
@ -156,10 +156,9 @@ impl service::rooms::short::Data for KeyValueDatabase {
.next() .next()
.ok_or_else(|| Error::bad_database("Invalid statekey in shortstatekey_statekey."))?; .ok_or_else(|| Error::bad_database("Invalid statekey in shortstatekey_statekey."))?;
let event_type = let event_type = StateEventType::from(str::from_utf8(eventtype_bytes).map_err(|_| {
StateEventType::from(utils::string_from_bytes(eventtype_bytes).map_err(|_| { Error::bad_database("Event type in shortstatekey_statekey is invalid unicode.")
Error::bad_database("Event type in shortstatekey_statekey is invalid unicode.") })?);
})?);
let state_key = utils::string_from_bytes(statekey_bytes).map_err(|_| { let state_key = utils::string_from_bytes(statekey_bytes).map_err(|_| {
Error::bad_database("Statekey in shortstatekey_statekey is invalid unicode.") Error::bad_database("Statekey in shortstatekey_statekey is invalid unicode.")

View file

@ -41,7 +41,7 @@ impl service::rooms::state::Data for KeyValueDatabase {
self.roomid_pduleaves self.roomid_pduleaves
.scan_prefix(prefix) .scan_prefix(prefix)
.map(|(_, bytes)| { .map(|(_, bytes)| {
EventId::parse_arc(utils::string_from_bytes(&bytes).map_err(|_| { EventId::parse_arc(str::from_utf8(&bytes).map_err(|_| {
Error::bad_database("EventID in roomid_pduleaves is invalid unicode.") Error::bad_database("EventID in roomid_pduleaves is invalid unicode.")
})?) })?)
.map_err(|_| Error::bad_database("EventId in roomid_pduleaves is invalid.")) .map_err(|_| Error::bad_database("EventId in roomid_pduleaves is invalid."))

View file

@ -258,7 +258,7 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
Box::new(self.roomserverids.scan_prefix(prefix).map(|(key, _)| { Box::new(self.roomserverids.scan_prefix(prefix).map(|(key, _)| {
ServerName::parse( ServerName::parse(
utils::string_from_bytes( str::from_utf8(
key.rsplit(|&b| b == 0xff) key.rsplit(|&b| b == 0xff)
.next() .next()
.expect("rsplit always returns an element"), .expect("rsplit always returns an element"),
@ -291,7 +291,7 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
Box::new(self.serverroomids.scan_prefix(prefix).map(|(key, _)| { Box::new(self.serverroomids.scan_prefix(prefix).map(|(key, _)| {
RoomId::parse( RoomId::parse(
utils::string_from_bytes( str::from_utf8(
key.rsplit(|&b| b == 0xff) key.rsplit(|&b| b == 0xff)
.next() .next()
.expect("rsplit always returns an element"), .expect("rsplit always returns an element"),
@ -313,7 +313,7 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
Box::new(self.roomuserid_joined.scan_prefix(prefix).map(|(key, _)| { Box::new(self.roomuserid_joined.scan_prefix(prefix).map(|(key, _)| {
UserId::parse( UserId::parse(
utils::string_from_bytes( str::from_utf8(
key.rsplit(|&b| b == 0xff) key.rsplit(|&b| b == 0xff)
.next() .next()
.expect("rsplit always returns an element"), .expect("rsplit always returns an element"),
@ -362,7 +362,7 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
.scan_prefix(prefix) .scan_prefix(prefix)
.map(|(key, _)| { .map(|(key, _)| {
UserId::parse( UserId::parse(
utils::string_from_bytes( str::from_utf8(
key.rsplit(|&b| b == 0xff) key.rsplit(|&b| b == 0xff)
.next() .next()
.expect("rsplit always returns an element"), .expect("rsplit always returns an element"),
@ -392,7 +392,7 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
.scan_prefix(prefix) .scan_prefix(prefix)
.map(|(key, _)| { .map(|(key, _)| {
UserId::parse( UserId::parse(
utils::string_from_bytes( str::from_utf8(
key.rsplit(|&b| b == 0xff) key.rsplit(|&b| b == 0xff)
.next() .next()
.expect("rsplit always returns an element"), .expect("rsplit always returns an element"),
@ -462,7 +462,7 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
.scan_prefix(user_id.as_bytes().to_vec()) .scan_prefix(user_id.as_bytes().to_vec())
.map(|(key, _)| { .map(|(key, _)| {
RoomId::parse( RoomId::parse(
utils::string_from_bytes( str::from_utf8(
key.rsplit(|&b| b == 0xff) key.rsplit(|&b| b == 0xff)
.next() .next()
.expect("rsplit always returns an element"), .expect("rsplit always returns an element"),

View file

@ -61,7 +61,7 @@ impl service::rooms::threads::Data for KeyValueDatabase {
users users
.split(|b| *b == 0xff) .split(|b| *b == 0xff)
.map(|bytes| { .map(|bytes| {
UserId::parse(utils::string_from_bytes(bytes).map_err(|_| { UserId::parse(str::from_utf8(bytes).map_err(|_| {
Error::bad_database("Invalid UserId bytes in threadid_userids.") Error::bad_database("Invalid UserId bytes in threadid_userids.")
})?) })?)
.map_err(|_| Error::bad_database("Invalid UserId in threadid_userids.")) .map_err(|_| Error::bad_database("Invalid UserId in threadid_userids."))

View file

@ -132,7 +132,7 @@ impl service::rooms::user::Data for KeyValueDatabase {
utils::common_elements(iterators, Ord::cmp) utils::common_elements(iterators, Ord::cmp)
.expect("users is not empty") .expect("users is not empty")
.map(|bytes| { .map(|bytes| {
RoomId::parse(utils::string_from_bytes(&bytes).map_err(|_| { RoomId::parse(str::from_utf8(&bytes).map_err(|_| {
Error::bad_database("Invalid RoomId bytes in userroomid_joined") Error::bad_database("Invalid RoomId bytes in userroomid_joined")
})?) })?)
.map_err(|_| Error::bad_database("Invalid RoomId in userroomid_joined.")) .map_err(|_| Error::bad_database("Invalid RoomId in userroomid_joined."))

View file

@ -155,7 +155,7 @@ fn parse_servercurrentevent(
let mut parts = key[1..].splitn(3, |&b| b == 0xff); let mut parts = key[1..].splitn(3, |&b| b == 0xff);
let user = parts.next().expect("splitn always returns one element"); let user = parts.next().expect("splitn always returns one element");
let user_string = utils::string_from_bytes(user) let user_string = str::from_utf8(user)
.map_err(|_| Error::bad_database("Invalid user string in servercurrentevent"))?; .map_err(|_| Error::bad_database("Invalid user string in servercurrentevent"))?;
let user_id = UserId::parse(user_string) let user_id = UserId::parse(user_string)
.map_err(|_| Error::bad_database("Invalid user id in servercurrentevent"))?; .map_err(|_| Error::bad_database("Invalid user id in servercurrentevent"))?;
@ -187,7 +187,7 @@ fn parse_servercurrentevent(
.next() .next()
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?; .ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
let server = utils::string_from_bytes(server).map_err(|_| { let server = str::from_utf8(server).map_err(|_| {
Error::bad_database("Invalid server bytes in server_currenttransaction") Error::bad_database("Invalid server bytes in server_currenttransaction")
})?; })?;

View file

@ -54,7 +54,7 @@ impl service::users::Data for KeyValueDatabase {
})?; })?;
Ok(Some(( Ok(Some((
UserId::parse(utils::string_from_bytes(user_bytes).map_err(|_| { UserId::parse(str::from_utf8(user_bytes).map_err(|_| {
Error::bad_database("User ID in token_userdeviceid is invalid unicode.") Error::bad_database("User ID in token_userdeviceid is invalid unicode.")
})?) })?)
.map_err(|_| { .map_err(|_| {
@ -72,7 +72,7 @@ impl service::users::Data for KeyValueDatabase {
/// Returns an iterator over all users on this homeserver. /// Returns an iterator over all users on this homeserver.
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a> { fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a> {
Box::new(self.userid_password.iter().map(|(bytes, _)| { Box::new(self.userid_password.iter().map(|(bytes, _)| {
UserId::parse(utils::string_from_bytes(&bytes).map_err(|_| { UserId::parse(str::from_utf8(&bytes).map_err(|_| {
Error::bad_database("User ID in userid_password is invalid unicode.") Error::bad_database("User ID in userid_password is invalid unicode.")
})?) })?)
.map_err(|_| Error::bad_database("User ID in userid_password is invalid.")) .map_err(|_| Error::bad_database("User ID in userid_password is invalid."))
@ -149,7 +149,7 @@ impl service::users::Data for KeyValueDatabase {
self.userid_avatarurl self.userid_avatarurl
.get(user_id.as_bytes())? .get(user_id.as_bytes())?
.map(|bytes| { .map(|bytes| {
utils::string_from_bytes(&bytes) str::from_utf8(&bytes)
.map_err(|_| Error::bad_database("Avatar URL in db is invalid.")) .map_err(|_| Error::bad_database("Avatar URL in db is invalid."))
.map(Into::into) .map(Into::into)
}) })
@ -269,7 +269,7 @@ impl service::users::Data for KeyValueDatabase {
self.userdeviceid_metadata self.userdeviceid_metadata
.scan_prefix(prefix) .scan_prefix(prefix)
.map(|(bytes, _)| { .map(|(bytes, _)| {
Ok(utils::string_from_bytes( Ok(str::from_utf8(
bytes.rsplit(|&b| b == 0xff).next().ok_or_else(|| { bytes.rsplit(|&b| b == 0xff).next().ok_or_else(|| {
Error::bad_database("UserDevice ID in db is invalid.") Error::bad_database("UserDevice ID in db is invalid.")
})?, })?,
@ -611,7 +611,7 @@ impl service::users::Data for KeyValueDatabase {
} }
}) })
.map(|(_, bytes)| { .map(|(_, bytes)| {
UserId::parse(utils::string_from_bytes(&bytes).map_err(|_| { UserId::parse(str::from_utf8(&bytes).map_err(|_| {
Error::bad_database( Error::bad_database(
"User ID in devicekeychangeid_userid is invalid unicode.", "User ID in devicekeychangeid_userid is invalid unicode.",
) )

View file

@ -489,7 +489,7 @@ impl KeyValueDatabase {
if services().globals.database_version()? < 2 { if services().globals.database_version()? < 2 {
// We accidentally inserted hashed versions of "" into the db instead of just "" // We accidentally inserted hashed versions of "" into the db instead of just ""
for (userid, password) in db.userid_password.iter() { for (userid, password) in db.userid_password.iter() {
let password = utils::string_from_bytes(&password); let password = str::from_utf8(&password);
let empty_hashed_password = password.is_ok_and(|password| { let empty_hashed_password = password.is_ok_and(|password| {
argon2::verify_encoded(&password, b"").unwrap_or(false) argon2::verify_encoded(&password, b"").unwrap_or(false)
@ -575,8 +575,8 @@ impl KeyValueDatabase {
if services().globals.database_version()? < 6 { if services().globals.database_version()? < 6 {
// Set room member count // Set room member count
for (roomid, _) in db.roomid_shortstatehash.iter() { for (roomid, _) in db.roomid_shortstatehash.iter() {
let string = utils::string_from_bytes(&roomid).unwrap(); let string = str::from_utf8(&roomid).unwrap();
let room_id = <&RoomId>::try_from(string.as_str()).unwrap(); let room_id = <&RoomId>::try_from(string).unwrap();
services().rooms.state_cache.update_joined_count(room_id)?; services().rooms.state_cache.update_joined_count(room_id)?;
} }
@ -681,8 +681,8 @@ impl KeyValueDatabase {
current_sstatehash = Some(sstatehash); current_sstatehash = Some(sstatehash);
let event_id = db.shorteventid_eventid.get(&seventid).unwrap().unwrap(); let event_id = db.shorteventid_eventid.get(&seventid).unwrap().unwrap();
let string = utils::string_from_bytes(&event_id).unwrap(); let string = str::from_utf8(&event_id).unwrap();
let event_id = <&EventId>::try_from(string.as_str()).unwrap(); let event_id = <&EventId>::try_from(string).unwrap();
let pdu = services() let pdu = services()
.rooms .rooms
.timeline .timeline

View file

@ -103,7 +103,7 @@ impl Service {
destination, destination,
status, status,
url, url,
crate::utils::string_from_bytes(&body) str::from_utf8(&body)
); );
} }

View file

@ -67,8 +67,11 @@ pub fn u64_from_bytes(bytes: &[u8]) -> Result<u64, std::array::TryFromSliceError
} }
/// Parses the bytes into a string. /// Parses the bytes into a string.
pub fn string_from_bytes(bytes: &[u8]) -> Result<String, std::string::FromUtf8Error> { ///
String::from_utf8(bytes.to_vec()) /// If `&str` is enough please use [str::from_utf8] to avoid unnecessary
/// allocation.
pub fn string_from_bytes(bytes: &[u8]) -> Result<String, std::str::Utf8Error> {
str::from_utf8(bytes).map(ToOwned::to_owned)
} }
pub fn random_string(length: usize) -> String { pub fn random_string(length: usize) -> String {